diff --git a/README.txt b/README.txt index 04d02bf9c71c2577cadb6bc829169b9c2f4bca93..bff09c7a2a0cc911d21f9ef7309ccdcb50e98a43 100644 --- a/README.txt +++ b/README.txt @@ -39,3 +39,7 @@ v0.3 -> Last stable commit on develop branch before the merge of feature-131-new v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0 v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support v0.5.1 -> Merge of bugfix-137-uplink-fixes. It includes stablity fixes for eNB +v0.5.2 -> Last version with old code for oaisim (abstraction mode works) +v0.6 -> RRH functionality, UE greatly improved, better TDD support, + a lot of bugs fixed. WARNING: oaisim in PHY abstraction mode does not + work, you need to use v0.5.2 for that. diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index bfd86cd183793e0a6088fb42c1090eb269003905..e20718ac3670650c90508cc3d17d0f66e37ca39a 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -114,6 +114,7 @@ endmacro(add_list_string_option) #################################################### # compilation flags ############################################# + #set(CMAKE_BUILD_TYPE "Debug") if (CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE "RelWithDebInfo") @@ -129,6 +130,9 @@ else (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") file(STRINGS "/proc/cpuinfo" CPUINFO REGEX flags LIMIT_COUNT 1) if (CPUINFO MATCHES "avx2") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mavx2") + set(COMPILATION_AVX2 "True") + else() + set(COMPILATION_AVX2 "False") endif() if (CPUINFO MATCHES "sse4_1") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1") @@ -170,7 +174,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU # these changes are related to hardcoded path to include .h files add_definitions(-DCMAKER) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2") set(GIT_BRANCH "UNKNOWN") @@ -195,7 +199,7 @@ if(GIT_FOUND) OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) - + # Get the latest commit date of the working branch execute_process( COMMAND git log -1 --format=%cd @@ -223,9 +227,9 @@ add_boolean_option(DISABLE_XER_PRINT False "print XER Format") add_boolean_option(XER_PRINT False "print XER Format") add_boolean_option(RRC_MSG_PRINT False "print RRC messages") add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.log") -add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace add_boolean_option(TEST_OMG False "???") add_boolean_option(DEBUG_OMG False "???") add_boolean_option(XFORMS False "This adds the possibility to see the signal oscilloscope") @@ -279,8 +283,10 @@ if (${RRC_ASN1_VERSION} STREQUAL "Rel8") set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1c/ASN1_files/EUTRA-RRC-Definitions-86.asn) elseif (${RRC_ASN1_VERSION} STREQUAL "CBA") set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1c/ASN1_files/EUTRA-RRC-Definitions-a20-lola.asn) -else() +elseif (${RRC_ASN1_VERSION} STREQUAL "Rel10") set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1c/ASN1_files/EUTRA-RRC-Definitions-a20.asn) +else() + set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1c/ASN1_files/RRC-e10.asn) endif (${RRC_ASN1_VERSION} STREQUAL "Rel8") set (RRC_FULL_DIR ${asn1_generated_dir}/${RRC_ASN1_VERSION}) @@ -486,35 +492,37 @@ add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET") include_directories("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/") include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/") #set (option_HWEXMIMOLIB_lib "-l ") -set(HWLIB_EXMIMO_SOURCE +set(HWLIB_EXMIMO_SOURCE ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c # ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c ) add_library(oai_exmimodevif MODULE ${HWLIB_EXMIMO_SOURCE} ) include_directories("${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/") -set (option_HWUSRPLIB_lib "-l uhd") -set(HWLIB_USRP_SOURCE +set(HWLIB_USRP_SOURCE ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp ) add_library(oai_usrpdevif MODULE ${HWLIB_USRP_SOURCE} ) +target_link_libraries(oai_usrpdevif uhd) include_directories("${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/") -set (option_HWBLADERFLIB_lib "-l bladerf") -set(HWLIB_BLADERF_SOURCE +set(HWLIB_BLADERF_SOURCE ${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c ) add_library(oai_bladerfdevif MODULE ${HWLIB_BLADERF_SOURCE} ) +target_link_libraries(oai_bladerfdevif bladeRF) include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/") -set(HWLIB_LMSSDR_SOURCE +set(HWLIB_LMSSDR_SOURCE ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp ) add_library(oai_lmssdrdevif MODULE ${HWLIB_LMSSDR_SOURCE} ) +target_include_directories(oai_lmssdrdevif PRIVATE /usr/local/include/lime) +target_link_libraries(oai_lmssdrdevif LimeSuite ) include_directories("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/") -set(TPLIB_ETHERNET_SOURCE +set(TPLIB_ETHERNET_SOURCE ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -522,69 +530,6 @@ set(TPLIB_ETHERNET_SOURCE add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} ) -# RF devices / transport protocols settings -###################################################################### -if (${RF_BOARD} STREQUAL "EXMIMO") - set(DRIVER2013) - include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/") - include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c) -# ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c) - set(option_HW_lib "-rdynamic -ldl") - -elseif (${RF_BOARD} STREQUAL "OAI_USRP") - include_directories("${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/") - include_directories("/opt/include/uhd") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp) - LINK_DIRECTORIES("/opt/lib") - set(option_HW_lib "-luhd -rdynamic -ldl -lboost_system") - -elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") - include_directories("${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") - include_directories("/usr/include") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c - ) - LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - - set(option_HW_lib "bladeRF -rdynamic -ldl") - -elseif (${RF_BOARD} STREQUAL "OAI_LMSSDR") - include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB") - include_directories("/usr/local/include/lime") - include_directories("/usr/include/lime") - LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/lmsSDR") - LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/lms7002m") - LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/Si5351C") - set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp) - set(option_HW_lib "-lLimeSuite -rdynamic -ldl") - -elseif (${RF_BOARD} STREQUAL "CPRIGW") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/CPRIGW/USERSPACE/LIB/cprigw_lib.c - ) - include_directories("${OPENAIR_TARGETS}/ARCH/CPRIGW/USERSPACE/LIB/") - set(option_HW_lib "-rdynamic dl") - -endif (${RF_BOARD} STREQUAL "EXMIMO") - - -if (${TRANSP_PRO} STREQUAL "ETHERNET") - - include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") - set(TRANSPORT_SOURCE ${TRANSPORT_SOURCE} - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c - ) - set(option_TP_lib "-rdynamic -ldl") - - -endif (${TRANSP_PRO} STREQUAL "ETHERNET") ########################################################## include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") @@ -837,13 +782,13 @@ include_directories("${OPENAIR_DIR}") if (FLEXRAN_AGENT_SB_IF) # set the version of protobuf messages, V3 not supported yet add_list1_option(FLPT_VERSION V2 "FLPT MSG protobuf grammar version" V2 V3) - + if (${FLPT_VERSION} STREQUAL "V2") set (FLPTDIR V2) elseif (${FLPT_VERSION} STREQUAL "V3") set (FLPTDIR V3) endif(${FLPT_VERSION} STREQUAL "V2") - + set(FLPT_MSG_DIR ${OPENAIR2_DIR}/ENB_APP/MESSAGES/${FLPTDIR} ) set(FLPT_MSG_FILES ${FLPT_MSG_DIR}/header.proto @@ -874,10 +819,10 @@ if (FLEXRAN_AGENT_SB_IF) ${FLPT_C_DIR}/config_common.pb-c.c ${FLPT_C_DIR}/control_delegation.pb-c.c ) - + file(GLOB flpt_h ${FLPT_C_DIR}/*.h) set(flpt_h ${flpt_h} ) - + add_library(FLPT_MSG ${FLPT_OAI_generated} ${FLPT_source} @@ -908,12 +853,12 @@ if (FLEXRAN_AGENT_SB_IF) ) set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT) #include_directories(${OPENAIR2_DIR}/ENB_APP) - + set(PROTOBUF_LIB "protobuf-c") - + FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h) FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml) - + INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES LIBYAML_INCLUDE_DIR) MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES) @@ -929,9 +874,9 @@ add_library(HASHTABLE include_directories(${OPENAIR_DIR}/common/utils/hashtable) if (MESSAGE_CHART_GENERATOR) - add_library(MSC + add_library(MSC ${OPENAIR_DIR}/common/utils/msc/msc.c - ) + ) set(MSC_LIB MSC) endif() include_directories(${OPENAIR_DIR}/common/utils/msc) @@ -1008,7 +953,7 @@ add_library(SECU_CN ${SECU_CN_SRC}) # Scheduler ################################" -set(SCHED_SRC +set(SCHED_SRC ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb.c ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_ue.c ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c @@ -1100,6 +1045,7 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c + ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c @@ -1114,6 +1060,11 @@ set(PHY_SRC if (${SMBV}) set(PHY_SRC "${PHY_SRC} ${OPENAIR1_DIR}/PHY/TOOLS/smbv.c") endif (${SMBV}) + +if (${COMPILATION_AVX2} STREQUAL "True") + set(PHY_SRC ${PHY_SRC} ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_llr_computation_avx2.c) +endif () + add_library(PHY ${PHY_SRC}) #Layer 2 library @@ -1301,7 +1252,7 @@ set(libnas_api_OBJS ${NAS_SRC}COMMON/API/NETWORK/nas_message.c ${NAS_SRC}COMMON/API/NETWORK/network_api.c ) - + set(libnas_emm_msg_OBJS ${NAS_SRC}COMMON/EMM/MSG/AttachAccept.c ${NAS_SRC}COMMON/EMM/MSG/AttachComplete.c @@ -1334,7 +1285,7 @@ set(libnas_emm_msg_OBJS ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateRequest.c ${NAS_SRC}COMMON/EMM/MSG/UplinkNasTransport.c ) - + set(libnas_esm_msg_OBJS ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.c ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.c @@ -1454,7 +1405,7 @@ set (libnas_utils_OBJS ${NAS_SRC}COMMON/UTIL/OctetString.c ) -if(NAS_UE) +if(NAS_UE) set(libnas_ue_api_OBJS ${NAS_SRC}UE/API/USER/at_command.c ${NAS_SRC}UE/API/USER/at_error.c @@ -1757,9 +1708,9 @@ add_executable(lte-softmodem ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c ${GTPU_need_ITTI} - ${HW_SOURCE} - ${TRANSPORT_SOURCE} ${RTAI_SOURCE} ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} @@ -1772,7 +1723,7 @@ target_link_libraries (lte-softmodem -ldl -Wl,--end-group ) target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) +target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-softmodem ${T_LIB}) @@ -1793,8 +1744,7 @@ add_executable(lte-softmodem-nos1 ${OPENAIR2_DIR}/RRC/NAS/nas_config.c ${OPENAIR2_DIR}/RRC/NAS/rb_config.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} + ${OPENAIR_DIR}/common/utils/system.c ${RTAI_SOURCE} ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} @@ -1806,7 +1756,7 @@ target_link_libraries (lte-softmodem-nos1 -Wl,--end-group ) target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) +target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) target_link_libraries (lte-softmodem-nos1 ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-softmodem-nos1 ${T_LIB}) @@ -1818,25 +1768,18 @@ add_executable(rrh_gw ${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c ${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c ${T_SOURCE} ) target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti) target_link_libraries(rrh_gw -Wl,--start-group - UTIL LFDS + UTIL LFDS -ldl -Wl,--end-group ) target_link_libraries (rrh_gw rt pthread m ) -target_link_libraries (rrh_gw ${option_HW_lib} ${option_TP_lib}) target_link_libraries (rrh_gw ${LIB_LMS_LIBRARIES}) target_link_libraries (rrh_gw ${T_LIB}) -Message("-- option_HW_lib=${option_HW_lib}") -Message("-- HW_SOURCE=${HW_SOURCE}") -Message("-- option_TP_lib=${option_TP_lib}") -Message("-- TRANSPORT_SOURCE=${TRANSPORT_SOURCE}") # USIM process ################# @@ -1887,10 +1830,10 @@ add_executable(oaisim ${OPENAIR2_DIR}/RRC/NAS/nas_config.c ${OPENAIR2_DIR}/RRC/NAS/rb_config.c ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c ${GTPU_need_ITTI} ${OPENAIR_TARGETS}/COMMON/create_tasks.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} ${XFORMS_SOURCE} ${T_SOURCE} ) @@ -1903,7 +1846,7 @@ target_link_libraries (oaisim -Wl,--end-group ) target_link_libraries (oaisim ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) -target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} +target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) #Force link with forms, regardless XFORMS option target_link_libraries (oaisim forms) @@ -1933,8 +1876,7 @@ add_executable(oaisim_nos1 ${OPENAIR2_DIR}/RRC/NAS/nas_config.c ${OPENAIR2_DIR}/RRC/NAS/rb_config.c ${OPENAIR_TARGETS}/COMMON/create_tasks.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} + ${OPENAIR_DIR}/common/utils/system.c ${XFORMS_SOURCE} ${T_SOURCE} ) @@ -1945,7 +1887,7 @@ target_link_libraries (oaisim_nos1 -Wl,--end-group ) target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) -target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} +target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) #Force link with forms, regardless XFORMS option target_link_libraries (oaisim_nos1 forms) @@ -1958,7 +1900,20 @@ target_link_libraries (oaisim_nos1 ${T_LIB}) # Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator ##################################### +#special case for dlim TM4, which uses its own version of phy_scope code +add_executable(dlsim_tm4 + ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c + ${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c + ${T_SOURCE} + ) +target_link_libraries (dlsim_tm4 + -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group + pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB} + ) + foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) + add_executable(${myExe} ${OPENAIR_BIN_DIR}/messages_xml.h ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c @@ -1983,7 +1938,7 @@ add_executable(test_epc_generate_scenario ${OPENAIR_BIN_DIR}/messages_xml.h ) target_link_libraries (test_epc_generate_scenario - -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} ) add_executable(test_epc_play_scenario @@ -2004,7 +1959,7 @@ add_executable(test_epc_play_scenario ) target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c) target_link_libraries (test_epc_play_scenario - -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} ) @@ -2024,7 +1979,7 @@ foreach(myExe s1ap ${OPENAIR3_DIR}/TEST/test_${myExe}.c ) target_link_libraries (test_${myExe} - -Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + -Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} ) endforeach(myExe) @@ -2034,21 +1989,22 @@ endforeach(myExe) #ensure that the T header files are generated before targets depending on them if (${T_TRACER}) - add_dependencies(lte-softmodem generate_T) - add_dependencies(lte-softmodem-nos1 generate_T) - add_dependencies(rrh_gw generate_T) - add_dependencies(oaisim generate_T) - add_dependencies(oaisim_nos1 generate_T) - add_dependencies(dlsim generate_T) - add_dependencies(dlsim_tm7 generate_T) - add_dependencies(ulsim generate_T) - add_dependencies(pbchsim generate_T) - add_dependencies(scansim generate_T) - add_dependencies(mbmssim generate_T) - add_dependencies(pdcchsim generate_T) - add_dependencies(pucchsim generate_T) - add_dependencies(prachsim generate_T) - add_dependencies(syncsim generate_T) + foreach(i + #all "add_executable" definitions (except tests, rb_tool, updatefw) + lte-softmodem lte-softmodem-nos1 rrh_gw oaisim oaisim_nos1 + dlsim_tm4 dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim + pdcchsim pucchsim prachsim syncsim + #all "add_library" definitions + ITTI RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB + oai_exmimodevif oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif + oai_eth_transpro + FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE MSC UTIL OMG_SUMO SECU_OSA + SECU_CN SCHED_LIB PHY L2 default_sched remote_sched RAL MIH CN_UTILS + GTPV1U SCTP_CLIENT UDP LIB_NAS_UE LFDS LFDS7 SIMU SIMU_ETH OPENAIR0_LIB) + if (TARGET ${i}) + add_dependencies(${i} generate_T) + endif() + endforeach(i) endif (${T_TRACER}) ################################################## @@ -2073,11 +2029,16 @@ endforeach() # force castxml and clang compilation with gnu89 standard # we can't use cXX standard as pthread_rwlock_t is gnu standard list(APPEND itti_compiler_options "-std=gnu89") - set (ITTI_H ${ITTI_DIR}/intertask_interface_types.h) +if(EXISTS /usr/bin/gccxml) + set(xml_command gccxml ${itti_compiler_options} -fxml=${OPENAIR_BIN_DIR}/messages.xml ${ITTI_H}) +else() + set(xml_command castxml --castxml-gccxml ${itti_compiler_options} ${ITTI_H} -o ${OPENAIR_BIN_DIR}/messages.xml) +endif() + add_custom_command ( OUTPUT ${OPENAIR_BIN_DIR}/messages.xml - COMMAND gccxml ${itti_compiler_options} -fxml=${OPENAIR_BIN_DIR}/messages.xml ${ITTI_H} + COMMAND ${xml_command} DEPENDS ${S1AP_OAI_generated} ${RRC_FULL_DIR}/asn1_constants.h ) @@ -2187,16 +2148,16 @@ make_driver(ue_ip ${OPENAIR2_DIR}/NETWORK_DRIVER/UE_IP ${ue_ip_src}) # OCTAVE tools ############### set(OCT_INCL -I${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS -I${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB -I${OPENAIR_TARGETS}/ARCH/COMMON) -set(OCT_LIBS -L${CMAKE_CURRENT_BINARY_DIR} -lm -lOPENAIR0_LIB) +set(OCT_LIBS -L${CMAKE_CURRENT_BINARY_DIR} -lm -lOPENAIR0_LIB) set(OCT_FLAGS -DEXMIMO) set(OCT_DIR ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/OCTAVE) set(OCT_FILES oarf_config_exmimo.oct - oarf_config_exmimo.oct - oarf_get_frame.oct - oarf_stop.oct - oarf_send_frame.oct - oarf_get_num_detected_cards.oct + oarf_config_exmimo.oct + oarf_get_frame.oct + oarf_stop.oct + oarf_send_frame.oct + oarf_get_num_detected_cards.oct oarf_stop_without_reset.oct ) @@ -2206,7 +2167,7 @@ foreach(file IN ITEMS ${OCT_FILES}) OUTPUT ${file} DEPENDS ${OCT_DIR}/${src} OPENAIR0_LIB COMMAND mkoctfile - ARGS ${OCT_FLAGS} ${OCT_INCL} ${OCT_LIBS} + ARGS ${OCT_FLAGS} ${OCT_INCL} ${OCT_LIBS} ARGS -o ${file} ${OCT_DIR}/${src} COMMENT "Generating ${file}" VERBATIM diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt index ca9a30546324be9cd3fa008e3b6b34bffd4af6b6..db49a9181d6009523a8e596b18d54add9603da16 100755 --- a/cmake_targets/at_commands/CMakeLists.txt +++ b/cmake_targets/at_commands/CMakeLists.txt @@ -88,31 +88,47 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse4.2 -std=gnu99 -Wall -Wstrict-prototype set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -DMALLOC_CHECK_=3") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ggdb -DMALLOC_CHECK_=3 -O2") -#This is to detect nettle version changes between Ubuntu 14.04/16.04 -set ( nettle_cmd "nettle-hash" ) -set ( nettle_arg "-V" ) -execute_process(COMMAND ${nettle_cmd} ${nettle_arg} RESULT_VARIABLE rv OUTPUT_VARIABLE ov ERROR_VARIABLE ev) +##This is to detect nettle version changes between Ubuntu 14.04/16.04 +#set ( nettle_cmd "nettle-hash" ) +#set ( nettle_arg "-V" ) +#execute_process(COMMAND ${nettle_cmd} ${nettle_arg} RESULT_VARIABLE rv OUTPUT_VARIABLE ov ERROR_VARIABLE ev) +# +#string(REGEX MATCH "[+-]?[0-9]+([.][0-9]+)?" nv ${ov}) +# +#message("NETTLE_VERSION = ${nv}") +# +## we need to remove decimal as floating point arithematic does not work properly with C preprocessor +#STRING(REGEX REPLACE "[.]" "" nv ${nv}) +# +#if ("${nv}" STREQUAL "") +# message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" ) +#endif() +# +#set (NETTLE_VERSION "${nv}") +#add_definitions("-DNETTLE_VERSION=${NETTLE_VERSION}") + +include(FindPkgConfig) -string(REGEX MATCH "[+-]?[0-9]+([.][0-9]+)?" nv ${ov}) +pkg_search_module(NETTLE nettle) +if(NOT ${NETTLE_FOUND}) + message( FATAL_ERROR "PACKAGE nettle not found: some targets will fail. Run build_oai -I again!") +else() + include_directories(${NETTLE_INCLUDE_DIRS}) +endif() -message("NETTLE_VERSION = ${nv}") +message ("NETTLE VERSION_INSTALLED = ${NETTLE_VERSION}") -# we need to remove decimal as floating point arithematic does not work properly with C preprocessor -STRING(REGEX REPLACE "[.]" "" nv ${nv}) +string(REGEX REPLACE "([0-9]+).*" "\\1" NETTLE_VERSION_MAJOR ${NETTLE_VERSION}) +string(REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" NETTLE_VERSION_MINOR ${NETTLE_VERSION}) +message ("NETTLE_VERSION_MAJOR = ${NETTLE_VERSION_MAJOR}") +message ("NETTLE_VERSION_MINOR = ${NETTLE_VERSION_MINOR}") -if ("${nv}" STREQUAL "") +if ("${NETTLE_VERSION_MAJOR}" STREQUAL "" OR "${NETTLE_VERSION_MINOR}" STREQUAL "") message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" ) endif() -set (NETTLE_VERSION "${nv}") -add_definitions("-DNETTLE_VERSION=${NETTLE_VERSION}") - -include(FindPkgConfig) - -INCLUDE(FindNettle) -IF( NOT NETTLE_FOUND ) - MESSAGE( SEND_ERROR "Nettle is required" ) -ENDIF( NOT NETTLE_FOUND ) +add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") +add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") pkg_search_module(OPENSSL openssl REQUIRED) @@ -215,8 +231,8 @@ set(api_user_HDR add_library(api_user ${api_user_SRC} ${api_user_HDR}) target_include_directories(api_user PRIVATE ${OPENAIR_NAS_DIR}/UE/API/USER - ${OPENAIR_NAS_DIR}/UE ${OPENAIR_NAS_DIR}/COMMON + ${OPENAIR_NAS_DIR}/UE ) ################################################################################ @@ -397,6 +413,7 @@ target_include_directories(emm PRIVATE ${OPENAIR_DIR}/common/utils/msc ${OPENAIR_DIR}/common/utils ${OPENAIR_DIR}/openair2/COMMON + ${OPENAIR_NAS_DIR}/UE ${OPENAIR_NAS_DIR}/UE/API/USIM ${OPENAIR_NAS_DIR}/UE/EMM ${OPENAIR_NAS_DIR}/COMMON/EMM/MSG @@ -409,7 +426,6 @@ target_include_directories(emm PRIVATE # esm LIB ################################################################################ set(esm_SRC - ${OPENAIR_NAS_DIR}/UE/ESM/esm_main.c ${OPENAIR_NAS_DIR}/UE/ESM/DedicatedEpsBearerContextActivation.c ${OPENAIR_NAS_DIR}/UE/ESM/DefaultEpsBearerContextActivation.c ${OPENAIR_NAS_DIR}/UE/ESM/EpsBearerContextDeactivation.c @@ -452,6 +468,7 @@ set(esm_SRC ) set(esm_HDR + ${OPENAIR_TARGETS}/COMMON/openairinterface5g_limits.h ${OPENAIR_NAS_DIR}/UE/ESM/esm_main.h ${OPENAIR_NAS_DIR}/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.h ${OPENAIR_NAS_DIR}/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.h @@ -481,13 +498,17 @@ set(esm_HDR ${OPENAIR_NAS_DIR}/UE/ESM/SAP/esm_recv.h ${OPENAIR_NAS_DIR}/UE/ESM/SAP/esm_sap.h ${OPENAIR_NAS_DIR}/UE/ESM/SAP/esm_send.h + ${OPENAIR_DIR}/common/utils/utils.h ) add_library(esm ${esm_SRC} ${esm_HDR}) target_include_directories(esm PRIVATE + ${OPENAIR_DIR}/common/utils + ${OPENAIR_NAS_DIR}/UE ${OPENAIR_NAS_DIR}/UE/API/USER ${OPENAIR_NAS_DIR}/UE/ESM + ${OPENAIR_TARGETS}/COMMON ${OPENAIR_NAS_DIR}/COMMON/ESM/MSG ${OPENAIR_NAS_DIR}/UE/ESM/SAP ${OPENAIR_NAS_DIR}/COMMON/IES @@ -670,6 +691,9 @@ target_include_directories(ies PRIVATE # EXECUTABLE at_nas_ue ################################################################################ include_directories( + ${OPENAIR_TARGETS}/COMMON + ${OPENAIR_NAS_DIR}/UE + ${OPENAIR_DIR}/common/utils ${OPENAIR_DIR}/common/utils/msc ${OPENAIR3_DIR}/COMMON ${OPENAIR3_DIR}/SECU @@ -691,6 +715,8 @@ ADD_EXECUTABLE(at_nas_ue ${OPENAIR_NAS_DIR}/UE/UEprocess.c ${OPENAIR_NAS_DIR}/UE/nas_parser.c ${OPENAIR_NAS_DIR}/UE/nas_proc.c ${OPENAIR_NAS_DIR}/UE/nas_user.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c ) target_link_libraries (at_nas_ue diff --git a/cmake_targets/autotests/README.txt b/cmake_targets/autotests/README.txt index 5841ed6dc20fe1e0212ee8124ac7ac95ee6d8dca..b94d99bff7b5a264ada3038a0027c3e6b3b786b1 100644 --- a/cmake_targets/autotests/README.txt +++ b/cmake_targets/autotests/README.txt @@ -101,6 +101,19 @@ Obj.# Case# Test# Description 01 51 04 pdcchsim (TBD) 01 51 05 pbchsim (TBD) 01 51 06 mbmssim (TBD) +01 51 10 dlsim_tm4 test cases (Test 1: 10 MHz, R2.FDD (MCS 5), EVA5, -1dB), + (Test 5: 1.4 MHz, R4.FDD (MCS 4), EVA5, 0dB (70%)), + (Test 6: 10 MHz, R3.FDD (MCS 15), EVA5, 6.7dB (70%)), + (Test 6b: 5 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (70%)), + (Test 7: 5 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (30%)), + (Test 7b: 5 MHz, R3-1.FDD (MCS 15), ETU70, 1.4 dB (30%)), + (Test 10: 5 MHz, R6.FDD (MCS 25), EVA5, 17.4 dB (70%)), + (Test 10b: 5 MHz, R6-1.FDD (MCS 24,18 PRB), EVA5, 17.5dB (70%)), + (Test 11: 10 MHz, R7.FDD (MCS 25), EVA5, 17.7dB (70%)) + (TM2 Test 1 10 MHz, R.11 FDD (MCS 14), EVA5, 6.8 dB (70%)), + (TM2 Test 1b 20 MHz, R.11-2 FDD (MCS 13), EVA5, 5.9 dB (70%)), + + 01 55 lte-softmodem tests with USRP B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for 1TX/1RX (TM1), 2TX/2RX (TM2) @@ -200,7 +213,7 @@ Obj.# Case# Test# Description 01 63 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 63 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX -01 65 00 lte-softmodem tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for 1TX/1RX +01 65 lte-softmodem tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for 1TX/1RX 01 65 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 65 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 65 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX @@ -209,7 +222,7 @@ Obj.# Case# Test# Description 01 65 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX -01 70 00 lte-softmodem tests with SoDeRa RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX +01 70 lte-softmodem tests with SoDeRa RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 70 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 70 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 70 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX @@ -218,7 +231,7 @@ Obj.# Case# Test# Description 01 70 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX -01 75 00 lte-softmodem + RRU (NGFI IF4P5, RAW) tests with B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX +01 75 lte-softmodem + RRU (NGFI IF4P5, RAW) tests with B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 75 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 75 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 75 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX @@ -226,7 +239,21 @@ Obj.# Case# Test# Description 01 75 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 75 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX -01 80 00 lte-softmodem + RRU (NGFI) tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX +01 76 lte-softmodem + RRU (NGFI IF4P5, UDP) tests with B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX +01 76 00 Band 7 FDD 5MHz UL Throughput (UDP) for 300 sec for 1TX/1RX +01 76 01 Band 7 FDD 10MHz UL Throughput (UDP) for 300 sec for 1TX/1RX +01 76 02 Band 7 FDD 20MHz UL Throughput (UDP) for 300 sec for 1TX/1RX +01 76 03 Band 7 FDD 5MHz DL Throughput (UDP) for 300 sec for 1TX/1RX +01 76 04 Band 7 FDD 10MHz DL Throughput (UDP) for 300 sec for 1TX/1RX +01 76 05 Band 7 FDD 20MHz DL Throughput (UDP) for 300 sec for 1TX/1RX +01 76 06 Band 7 FDD 5MHz UL Throughput (TCP) for 300 sec for 1TX/1RX +01 76 07 Band 7 FDD 10MHz UL Throughput (TCP) for 300 sec for 1TX/1RX +01 76 08 Band 7 FDD 20MHz UL Throughput (TCP) for 300 sec for 1TX/1RX +01 76 09 Band 7 FDD 5MHz DL Throughput (TCP) for 300 sec for 1TX/1RX +01 76 10 Band 7 FDD 10MHz DL Throughput (TCP) for 300 sec for 1TX/1RX +01 76 11 Band 7 FDD 20MHz DL Throughput (TCP) for 300 sec for 1TX/1RX + +01 80 lte-softmodem + RRU (NGFI) tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 80 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 80 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 80 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX @@ -234,7 +261,7 @@ Obj.# Case# Test# Description 01 80 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 80 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX -01 85 00 lte-softmodem + RRU (NGFI) tests with USRP X310 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX +01 85 lte-softmodem + RRU (NGFI) tests with USRP X310 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 85 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 85 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 85 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX @@ -242,6 +269,32 @@ Obj.# Case# Test# Description 01 85 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 85 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX +01 86 lte-softmodem tests with USRP B210 RF as eNB and ALU EPC w/ Huawei e3276 COTS UE for 1TX/1RX (TM1), 2TX/2RX (TM2) +01 86 00 Band 38 TDD 5MHz UL Throughput (UDP) for 300 sec for 1TX/1RX +01 86 01 Band 38 TDD 10MHz UL Throughput (UDP) for 300 sec for 1TX/1RX +01 86 02 Band 38 TDD 20MHz UL Throughput (UDP) for 300 sec for 1TX/1RX +01 86 03 Band 38 TDD 5MHz DL Throughput (UDP) for 300 sec for 1TX/1RX +01 86 04 Band 38 TDD 10MHz DL Throughput (UDP) for 300 sec for 1TX/1RX +01 86 05 Band 38 TDD 20MHz DL Throughput (UDP) for 300 sec for 1TX/1RX +01 86 06 Band 38 TDD 5MHz UL Throughput (UDP) for 300 sec for 2TX/2RX (TM2) +01 86 07 Band 38 TDD 10MHz UL Throughput (UDP) for 300 sec for 2TX/2RX (TM2) +01 86 08 Band 38 TDD 20MHz UL Throughput (UDP) for 300 sec for 2TX/2RX (TM2) +01 86 09 Band 38 TDD 5MHz DL Throughput (UDP) for 300 sec for 2TX/2RX (TM2) +01 86 10 Band 38 TDD 10MHz DL Throughput (UDP) for 300 sec for 2TX/2RX (TM2) +01 86 11 Band 38 TDD 20MHz DL Throughput (UDP) for 300 sec for 2TX/2RX (TM2) +01 86 12 Band 38 TDD 5MHz UL Throughput (TCP) for 300 sec for 1TX/1RX +01 86 13 Band 38 TDD 10MHz UL Throughput (TCP) for 300 sec for 1TX/1RX +01 86 14 Band 38 TDD 20MHz UL Throughput (TCP) for 300 sec for 1TX/1RX +01 86 15 Band 38 TDD 5MHz DL Throughput (TCP) for 300 sec for 1TX/1RX +01 86 16 Band 38 TDD 10MHz DL Throughput (TCP) for 300 sec for 1TX/1RX +01 86 17 Band 38 TDD 20MHz DL Throughput (TCP) for 300 sec for 1TX/1RX +01 86 18 Band 38 TDD 5MHz UL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) +01 86 19 Band 38 TDD 10MHz UL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) +01 86 20 Band 38 TDD 20MHz UL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) +01 86 21 Band 38 TDD 5MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) +01 86 22 Band 38 TDD 10MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) +01 86 23 Band 38 TDD 20MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) + 02 55 lte-softmodem tests with USRP B210 RF as eNB and ALU EPC w/ Sony Experia M4 COTS UE for 1TX/1RX and 2TX/2RX (TM2) 02 55 00 Band 7 FDD 5MHz UL Throughput (UDP) for 300 sec for 1TX/1RX 02 55 01 Band 7 FDD 10MHz UL Throughput (UDP) for 300 sec for 1TX/1RX diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index e51b57e6ec1e23c753f8f4cddbb742efb210517a..0c80e960a45286fe34d3387d3c0783267cb63dc7 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -994,6 +994,43 @@ <nruns>3</nruns> </testCase> + <testCase id="015110"> + <class>execution</class> + <desc>dlsim_tm4 test cases (Test 1: 10 MHz, R2.FDD (MCS 5), EVA5, -1dB), + (Test 5: 1.4 MHz, R4.FDD (MCS 4), EVA5, 0dB (70%)), + (Test 6, 10 MHz, R3.FDD (MCS 15), EVA5, 6.7dB (70%)), + (Test 6b, 5 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (70%)), + (Test 7, 5 MHz, R3-1.FDD (MCS 15), EVA5, 6.7dB (30%)), + (Test 7b, 5 MHz, R3-1.FDD (MCS 15), ETU70, 1.4 dB (30%)), + (Test 10, 5 MHz, R6.FDD (MCS 25), EVA5, 17.4 dB (70%)), + (Test 10b, 5 MHz, R6-1.FDD (MCS 24,18 PRB), EVA5, 17.5dB (70%)), + (Test 11, 10 MHz, R7.FDD (MCS 25), EVA5, 17.7dB (70%)) + (TM2 Test 1 10 MHz, R.11 FDD (MCS 14), EVA5, 6.8 dB (70%)), + (TM2 Test 1b 20 MHz, R.11-2 FDD (MCS 13), EVA5, 5.9 dB (70%)), + </desc> + <pre_compile_prog></pre_compile_prog> + <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog> + <compile_prog_args> --phy_simulators -c </compile_prog_args> + <pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash</pre_exec> + <pre_exec_args></pre_exec_args> + <main_exec> $OPENAIR_DIR/cmake_targets/lte-simulators/build/dlsim_tm4</main_exec> + <main_exec_args> -m5 -gF -s-1 -w1.0 -f.2 -n500 -B50 -c2 -z2 -O70 + -m4 -gF -s0 -w1.0 -f.2 -n500 -B6 -c4 -z2 -O70 + -m15 -gF -s6.7 -w1.0 -f.2 -n500 -B50 -c2 -z2 -O70 + -m14 -gF -s6.7 -w1.0 -f.2 -n500 -B25 -c3 -z2 -O70 + -m15 -gG -s6.7 -w1.0 -f.2 -n500 -B50 -c2 -z2 -O30 + -m14 -gG -s1.4 -w1.0 -f.2 -n500 -B25 -c3 -z2 -O30 + -m25 -gF -s17.4 -w1.0 -f.2 -n500 -B25 -c3 -z2 -O70 + -m25 -gF -s17.5 -w1.0 -f.2 -n500 -B25 -c3 -z2 -r1022 -O70 + -m26 -gF -s17.7 -w1.0 -f.2 -n500 -B50 -c2 -z2 -O70 + -m14 -gF -s6.8 -w1.0 -f.2 -n500 -B50 -c2 -x2 -y2 -z2 -O70 + -m13 -gF -s5.9 -w1.0 -f.2 -n500 -B25 -c3 -x2 -y2 -z2 -O70</main_exec_args> + <tags>dlsim_tm4.test1 dlsim_tm4.test5 dlsim_tm4.test6 dlsim_tm4.test6b dlsim_tm4.test7 dlsim_tm4.test7b dlsim_tm4.test10 dlsim_tm4.test10b dlsim_tm4.test11 dlsim_tm4.TM2_test1 dlsim_tm4.TM2_test1b</tags> + <search_expr_true>"passed"</search_expr_true> + <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false> + <nruns>3</nruns> + </testCase> + <testCase id="015500" > <class>lte-softmodem</class> <desc></desc> @@ -8627,6 +8664,43 @@ c <nruns>10</nruns> </testCase> + <testCase id="017600"></testCase> + <testCase id="017601"></testCase> + <testCase id="017602"></testCase> + <testCase id="017603"></testCase> + <testCase id="017604"></testCase> + <testCase id="017605"></testCase> + <testCase id="017606"></testCase> + <testCase id="017607"></testCase> + <testCase id="017608"></testCase> + <testCase id="017609"></testCase> + <testCase id="017610"></testCase> + <testCase id="017611"></testCase> + + <testCase id="018600"></testCase> + <testCase id="018601"></testCase> + <testCase id="018602"></testCase> + <testCase id="018603"></testCase> + <testCase id="018604"></testCase> + <testCase id="018605"></testCase> + <testCase id="018606"></testCase> + <testCase id="018607"></testCase> + <testCase id="018608"></testCase> + <testCase id="018609"></testCase> + <testCase id="018610"></testCase> + <testCase id="018611"></testCase> + <testCase id="018612"></testCase> + <testCase id="018613"></testCase> + <testCase id="018614"></testCase> + <testCase id="018615"></testCase> + <testCase id="018616"></testCase> + <testCase id="018617"></testCase> + <testCase id="018618"></testCase> + <testCase id="018619"></testCase> + <testCase id="018620"></testCase> + <testCase id="018621"></testCase> + <testCase id="018622"></testCase> + <testCase id="018623"></testCase> <testCase id="025500" > <class>lte-softmodem</class> diff --git a/cmake_targets/autotests/testsuite_ue_noS1.xml b/cmake_targets/autotests/testsuite_ue_noS1.xml index c5403feab237aeba20fe2b196d27e0db7983573a..f88244e7ef2a8efa10580fcb5f485f67433827e2 100644 --- a/cmake_targets/autotests/testsuite_ue_noS1.xml +++ b/cmake_targets/autotests/testsuite_ue_noS1.xml @@ -3208,6 +3208,316 @@ + <!--20 MHz test --> + +<testCase id="039400" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>imb182-desktop</eNB> + <UE>yanbo-M4HM87P-00</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 28 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "55008"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.20MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="036600" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>imb182-desktop</eNB> + <UE>yanbo-M4HM87P-00</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 0 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "2040"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.20MHZ.MCS0</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="038400" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>imb182-desktop</eNB> + <UE>yanbo-M4HM87P-00</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 18 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "23976"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.20MHZ.MCS18</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + + <testCase id="036630" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>imb182-desktop</eNB> + <UE>yanbo-M4HM87P-00</UE> + <TimeOut_cmd>700</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 0</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>600</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.20MHZ.MCS0</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="038430" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>imb182-desktop</eNB> + <UE>yanbo-M4HM87P-00</UE> + <TimeOut_cmd>700</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 18</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 24M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>600</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.20MHZ.MCS18</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + + <testCase id="039430" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>imb182-desktop</eNB> + <UE>yanbo-M4HM87P-00</UE> + <TimeOut_cmd>700</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 28</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 55M</eNB_traffic_exec> <!-- PHY max TP 73.334Mbps -> 75% = 55Mbps --> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>600</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.20MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + </testCaseList> diff --git a/cmake_targets/autotests/testsuite_ue_noS1_TCL.xml b/cmake_targets/autotests/testsuite_ue_noS1_TCL.xml new file mode 100644 index 0000000000000000000000000000000000000000..971819ade587c7d578da052e43ab7cc7de55a8b6 --- /dev/null +++ b/cmake_targets/autotests/testsuite_ue_noS1_TCL.xml @@ -0,0 +1,3516 @@ +<testCaseList> + +<MachineList>TCT-Labo1 TCT-Labo3</MachineList> <!-- ued-PRM-130 --> + <NFSResultsShare>/mnt/sradio/TEST_RESULTS/</NFSResultsShare> + <GitOAI5GRepo> https://gitlab.eurecom.fr/oai/openairinterface5g.git</GitOAI5GRepo> + <!-- <GitOAI5GRepo>https://gitlab.eurecom.fr/oai/openairinterface5g.git</GitOAI5GRepo> --> + <!-- <GitOAI5GRepo>git@gitlab.com:TCL_Communications/openairinterface5g.git</GitOAI5GRepo> --> + <GitOpenair-cnRepo>https://gitlab.eurecom.fr/oai/openair-cn.git</GitOpenair-cnRepo> --> + <!--<GitOAI5GRepoBranch>develop_integration_w15</GitOAI5GRepoBranch>--> + <GitOAI5GRepoBranch>eNB_phy-test_fix_20MHz</GitOAI5GRepoBranch> + <GitOAI5GHeadVersion>eNB_phy-test_fix_20MHz</GitOAI5GHeadVersion> --> + <!-- <GitOAI5GHeadVersion>425b6fd525d9c4b0b3c2357926bbac5685e4b1e5</GitOAI5GHeadVersion> --> + <!-- <GitOAI5GHeadVersion>23822ea203e00f2100fa41c7ee3084ec55b884fe</GitOAI5GHeadVersion> --> + <!-- <GitOAI5GHeadVersion></GitOAI5GHeadVersion>--> + <!-- <OAI5GPatchDir></OAI5GPatchDir>--> + + <!-- + <OAI5GPatchFile name="phy_test_dl_harq_reset.patch"/> + <OAI5GPatchFile name="phy_test__target_dl_mcs.patch"/> + <OAI5GPatchFile name="pdcp_fifo_netlink.patch"/> +--> + + <GitOpenair-cnRepoBranch>develop</GitOpenair-cnRepoBranch> + <CleanUpOldProgs>oaisim oaisim_nos1 lte-softmodem lte-softmodem-nos1 mme_gw run_epc auth_request run_hss oai_hss mme spgw hss hss_sim configure_cots* wvdial iperf iperf_script iperf_script_phone ping tshark rrh_gw iperf3 iperf3_script iperf3_script_phone pppd</CleanUpOldProgs> + <CleanUpAluLteBox>sudo -S -E /opt/ltebox/tools/stop_ltebox</CleanUpAluLteBox> +<ExmimoRfStop>$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg</ExmimoRfStop> + <Timeout_execution>36000</Timeout_execution> + <TestCaseExclusionList></TestCaseExclusionList> + <nruns_lte-softmodem></nruns_lte-softmodem> + <MachineListGeneric>TCT-Labo3</MachineListGeneric> + + +<!-- USRP Testcases performances 030000 030030 030100 030900 030930 031000 031030 031600 031630 031700 031730 031800 031900 031930 032000 032100 032200 032300 032400 032500 032600 032700 032710 032730 032740 032800 032810 032830 032840 032870 036000 036100 036130 036170 --> + +<!-- USRP Testcases performances 030000 030030 030900 030930 031000 031030 031600 031630 031700 031730 031900 031930 032700 032730 032800 036000 036100 036130 032740 032710 --> + +<!-- Stability 032740 032710 --> + + + <!-- USRP Band 7 5MHz SISO Iperf downlink performances : 030030 030930 031030 031630 031730 031930 032730 032830 --> + + + + +<!-- PHY-TEST DOWNLINK PERFORMANCE --> + + + <testCase id="030000" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 0 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "510"/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS00</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="030001" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 0 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "510"/> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS00</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="030100" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 1 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "678"/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS01</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="030101" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 1 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "678"/> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS01</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + + +<testCase id="030900" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 9 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "3006"/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS09</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="030901" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 9 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "3006"/> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS09</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="031600" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 16 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "3726"/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS16</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="031601" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 16 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "3726"/> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS16</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="031000" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 10 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS10</tags> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "3006"/> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="031001" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 10 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS10</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "3006"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="031700" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 17 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS17</tags> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "5802"/> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="031701" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 17 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS17</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "5802"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="031800" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 18 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS18</tags> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "5994"/> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="031801" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 18 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS18</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "5994"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="031900" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 19 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS19</tags> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "6858"/> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="031901" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 19 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS19</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "6858"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + +<testCase id="032000" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 20 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS20</tags> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "7434"/> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032001" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 20 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS20</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "7434"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032100" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 21 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS21</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "8010"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032101" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 21 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS21</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "8010"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="032200" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 22 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS22</tags> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "8586"/> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032201" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 22 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS22</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "8586"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="032300" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 23 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS23</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "9432"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032301" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 23 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS23</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "9432"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="032400" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 24 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS24</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "10152"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032401" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 24 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS24</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "10152"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + +<testCase id="032500" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 25 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS25</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "10584"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032501" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 25 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS25</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "10584"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="032600" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 26 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS26</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11448"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032601" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 26 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS26</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11448"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + +<testCase id="032700" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11880"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032701" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11880"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032801" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "13752"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + +<testCase id="032710" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>3600</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS27</tags> + <nruns>1</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11880"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="032711" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11880"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="036000" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test </eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2685000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "22193"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + <testCase id="036001" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2685000000 -r50 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "22193"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="036100" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2685000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "25687"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + <testCase id="035201" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 19 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2685000000 -r50 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS19</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "12835"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + <testCase id="036130" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 30M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2685000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.10MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + + <testCase id="030031" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 0</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 512K</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS00</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + <testCase id="030931" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 9 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS09</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + <testCase id="031031" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 10 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS10</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + + <testCase id="031631" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 16 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS16</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + <testCase id="031731" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 17 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS17</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + + + + <testCase id="031931" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 19 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 10M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS19</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + <testCase id="032740" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>3600</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>2800</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF_STAB.BAND7.5MHZ.MCS27</tags> + <nruns>1</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="032731" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>ued-PRM-130</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <!-- USRP Band 7 5MHz SISO Iperf downlink performances --> + <!-- 030030 030930 031030 031630 031730 031930 032730 032830 --> + + <testCase id="030030" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 0 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 512K</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS00</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + <testCase id="030930" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 9 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS09</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="031030" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 10 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS10</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + <testCase id="031630" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 16 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS16</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="031730" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 17 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS17</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="031930" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 19 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS19</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + <testCase id="032730" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1 </eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 27 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 30;iperf -c 10.0.1.9 -i 1 -u -b 15M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS27</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + </testCase> + + + + + + + + + + + + <testCase id="032800" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "13752"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + <testCase id="032810" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>18000</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "11880"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS28</tags> + <nruns>1</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="032830" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1 </eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 30;iperf -c 10.0.1.9 -i 1 -u -b 13700K</eNB_traffic_exec> <!-- PHY max TP 18.336Mbps -> 75% = 13.70Mbps --> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <UE_traffic_metric + mode="UDP" + duration_min="200" + + /> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.5MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="032840" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>3600</TimeOut_cmd> + <tags>UE_USRP.NOS1.DATA_IPERF_STAB_DL.BAND7.5MHZ.MCS28</tags> + <nruns>1</nruns><max_ntries>6</max_ntries> + + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>2800</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + + </testCase> + + + + <testCase id="032870" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1 </eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 30;iperf -c 10.0.1.9 -i 1</eNB_traffic_exec> <!-- PHY max TP 18.336Mbps -> 75% = 13.70Mbps --> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <UE_traffic_metric + mode="TCP" + duration_min="200" + bandwidth_min="13.7" + /> + <tags>UE_USRP.NOS1.DATA_IPERF_TCP_DL.BAND7.5MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="036170" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf downlink_frequency 2660000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2685000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 24 --ue-rxgain 100 -S</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>200</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <tags>UE_USRP.NOS1.DATA_IPERF_TCP_DL.BAND7.10MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <UE_traffic_metric + mode="TCP" + duration_min="200" + bandwidth_min="27.5" + /> + </testCase> + + + <!--20 MHz test --> + +<testCase id="039400" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 28 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "55008"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.20MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="036600" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 0 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "2040"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.20MHZ.MCS0</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="038400" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>300</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 18 --single-thread-disable --phy-test</eNB_main_exec_args> + <eNB_traffic_exec></eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 -S --phy-test</UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec></UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true></UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps" + pass_fail_stat = "mean_value" + min_limit = "23976"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.20MHZ.MCS18</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + + <testCase id="036630" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>700</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 0</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>600</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.20MHZ.MCS0</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + <testCase id="038430" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>700</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 18</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 24M</eNB_traffic_exec> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>600</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.20MHZ.MCS18</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + + <testCase id="039430" > + <class>lte-softmodem-noS1</class> + <desc></desc> + <eNB>TCT-Labo1</eNB> + <UE>TCT-Labo3</UE> + <TimeOut_cmd>700</TimeOut_cmd> + <eNB_working_dir>/tmp</eNB_working_dir> + <eNB_config_file>targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf downlink_frequency 2680000000L</eNB_config_file> + <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog> + <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args> + <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec> + <eNB_pre_exec_args></eNB_pre_exec_args> + <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec> + <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf -m 28</eNB_main_exec_args> + <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 55M</eNB_traffic_exec> <!-- PHY max TP 73.334Mbps -> 75% = 55Mbps --> + <eNB_traffic_exec_args></eNB_traffic_exec_args> + <eNB_search_expr_true></eNB_search_expr_true> + <eNB_search_expr_false></eNB_search_expr_false> + <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs> + + <UE_working_dir>/tmp</UE_working_dir> + <UE_config_file></UE_config_file> + <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog> + <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args> + <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec> + <UE_pre_exec_args></UE_pre_exec_args> + <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2680000000 -r100 --ue-scan-carrier --ue-txgain 85 --ue-rxgain 100 </UE_main_exec> + <UE_main_exec_args></UE_main_exec_args> + <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec> + <UE_traffic_exec_args></UE_traffic_exec_args> + <UE_search_expr_true>600</UE_search_expr_true> + <UE_search_expr_false></UE_search_expr_false> + <UE_terminate_missing_procs>False</UE_terminate_missing_procs> + <UE_metric id="UE_DLSCH_BITRATE" + description="UE downlink physical throughput" + regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' + unit_of_meas = "kbps"/> + <UE_metric id="UE_FREQ_OFFSET" + description="UE downlink frequency channel offset" + regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' + unit_of_meas = "Hz"/> + <UE_metric id="UE_RX_OFFSET" + description="UE downlink rx sample offset" + regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' + unit_of_meas = ""/> + <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.20MHZ.MCS28</tags> + <nruns>3</nruns><max_ntries>6</max_ntries> + </testCase> + + + + + </testCaseList> + diff --git a/cmake_targets/autotests/v2/actions/alu_hss.bash b/cmake_targets/autotests/v2/actions/alu_hss.bash index ded1e352ce8dde0f861a2d2b5608e60b8fbbd282..be32fe9eb08d8d7c75292dcef1c35ad422ad17ec 100644 --- a/cmake_targets/autotests/v2/actions/alu_hss.bash +++ b/cmake_targets/autotests/v2/actions/alu_hss.bash @@ -1,2 +1,4 @@ +sudo rmmod nasmesh || true +sudo rmmod ue_ip || true sudo /opt/ltebox/tools/stop_ltebox || true sudo /opt/hss_sim0609/starthss_real diff --git a/cmake_targets/autotests/v2/actions/execution_compile.bash b/cmake_targets/autotests/v2/actions/execution_compile.bash index 530447ebcdb0f5639db86138d9f2bab0dc75b9ed..149ebdff85f179ee5593e68c87aaf7c7a9abbfe1 100644 --- a/cmake_targets/autotests/v2/actions/execution_compile.bash +++ b/cmake_targets/autotests/v2/actions/execution_compile.bash @@ -1,5 +1,7 @@ cd /tmp/oai_test_setup/oai source oaienv +sudo rmmod nasmesh || true +sudo rmmod ue_ip || true cd cmake_targets rm -rf log mkdir -p log diff --git a/cmake_targets/autotests/v2/actions/run_enb.bash b/cmake_targets/autotests/v2/actions/run_enb.bash index 1a4c5368a7453f83b446afcc92a69a1744610995..abf7dc028624bce03cf001ca701a695ebcc3637c 100644 --- a/cmake_targets/autotests/v2/actions/run_enb.bash +++ b/cmake_targets/autotests/v2/actions/run_enb.bash @@ -3,6 +3,8 @@ stty isig intr ^C cd /tmp/oai_test_setup/oai source oaienv +sudo rmmod nasmesh || true +sudo rmmod ue_ip || true cd cmake_targets/lte_build_oai/build ulimit -c unlimited sudo rm -f core diff --git a/cmake_targets/autotests/v2/actions/start_3276.bash b/cmake_targets/autotests/v2/actions/start_3276.bash new file mode 100644 index 0000000000000000000000000000000000000000..380c914d47ca57e23a5d17a2697b8eee9573dc02 --- /dev/null +++ b/cmake_targets/autotests/v2/actions/start_3276.bash @@ -0,0 +1,13 @@ +#enable control+C reception (to be refined if it does not work) +stty isig intr ^C + +cd /tmp/oai_test_setup/oai +source oaienv +sudo rmmod nasmesh || true +sudo rmmod ue_ip || true +cd cmake_targets/autotests/v2/actions +sudo python start_3276.py + +sudo wvdial -C wvdial.3276.conf || true + +sudo python stop_3276.py diff --git a/cmake_targets/autotests/v2/actions/start_3276.py b/cmake_targets/autotests/v2/actions/start_3276.py new file mode 100644 index 0000000000000000000000000000000000000000..cf0629213aa012ea25b76ead78c6af332fe15c38 --- /dev/null +++ b/cmake_targets/autotests/v2/actions/start_3276.py @@ -0,0 +1,59 @@ +import time + +from modem import quit, Modem + +try: + modem = Modem("/dev/ttyUSB0") + + #test that modem is there + print "INFO: check modem's presence" + modem.send('AT') + if modem.wait().ret != True: + print "ERROR: no modem?" + quit(1) + + #first deactivate + print "INFO: deactivate the modem" + modem.send('AT+CFUN=0') + if modem.wait().ret != True: + print "ERROR: failed deactivating the modem" + quit(1) + + #activate the modem + print "INFO: activate the modem" + modem.send('AT+CFUN=1') + if modem.wait().ret != True: + print "ERROR: failed asking modem for activation" + quit(1) + + #wait for modem to be connected + #timeout after one minute + print "INFO: wait for modem to be connected (timeout: one minute)" + start_time = time.time() + while True: + modem.send('AT+CGATT?') + r = modem.wait() + if r.ret != True: + print "ERROR: failed checking attachment status of modem" + quit(1) + if "+CGATT: 1" in r.data: + break + if not "CGATT: 0" in r.data: + print "ERROR: bad data when checking attachment status of modem" + quit(1) + time.sleep(0.1) + if time.time() > start_time + 60: + print "ERROR: modem not connected after one minute, close modem" + modem.send('AT+CFUN=0') + r = modem.wait() + if r.ret != True: + print "ERROR: closing modem failed" + quit(1) + + print "INFO: modem is connected" + +except BaseException, e: + print "ERROR: " + str(e) + quit(1) + +quit(0) diff --git a/cmake_targets/autotests/v2/actions/start_bandrich.bash b/cmake_targets/autotests/v2/actions/start_bandrich.bash index e562dfc29be777b4c09e9e87cb53d620533b7dc3..7620e897842010f040696db8b49975be727e06f4 100644 --- a/cmake_targets/autotests/v2/actions/start_bandrich.bash +++ b/cmake_targets/autotests/v2/actions/start_bandrich.bash @@ -16,6 +16,8 @@ stty isig intr ^C cd /tmp/oai_test_setup/oai source oaienv +sudo rmmod nasmesh || true +sudo rmmod ue_ip || true cd cmake_targets/autotests/v2/actions python start_bandrich.py diff --git a/cmake_targets/autotests/v2/actions/stop_3276.py b/cmake_targets/autotests/v2/actions/stop_3276.py new file mode 100644 index 0000000000000000000000000000000000000000..3eb7e889c6b91020028d17e6844523f79c2f58d3 --- /dev/null +++ b/cmake_targets/autotests/v2/actions/stop_3276.py @@ -0,0 +1,29 @@ +import time + +from modem import quit, Modem + +try: + modem = Modem("/dev/ttyUSB0") + + #test that modem is there + print "INFO: check modem's presence" + modem.send('AT') + r = modem.wait() + if r.ret != True and "NO CARRIER" not in r.data: + print "ERROR: no modem?" + quit(1) + if "NO CARRIER" in r.data: + print "WARNING: 'NO CARRIER' detected, not sure if handled correctly" + + #deactivate the modem + print "INFO: deactivate the modem" + modem.send('AT+CFUN=0') + if modem.wait().ret != True: + print "ERROR: failed asking modem for deactivation" + quit(1) + +except BaseException, e: + print "ERROR: " + str(e) + quit(1) + +quit(0) diff --git a/cmake_targets/autotests/v2/actions/wvdial.3276.conf b/cmake_targets/autotests/v2/actions/wvdial.3276.conf new file mode 100644 index 0000000000000000000000000000000000000000..81fedc8df212d7183b2902373a8151ad4f48c171 --- /dev/null +++ b/cmake_targets/autotests/v2/actions/wvdial.3276.conf @@ -0,0 +1,27 @@ +[Dialer Defaults] +Modem = /dev/ttyUSB0 +ISDN = off +Modem Type = Analog Modem +Baud = 9600 +Init1 = ATZ +Init2 = AT&F &D2 &C1 +Init3 = AT+CGDCONT=1,"IP","oai.ipv4" +Phone = *99# +Phone1 = +Phone2 = +Phone3 = +Phone4 = +Ask Password = off +Password = '' +Username = ImaginLab +Auto Reconnect = off +Abort on Busy = off +Carrier Check = on +Check Def Route = on +Abort on No Dialtone = on +Stupid Mode = on +Idle Seconds = 0 +Auto DNS = on +;Minimize = off +;Dock = off +;Do NOT edit this file by hand! diff --git a/cmake_targets/autotests/v2/alu_test.py b/cmake_targets/autotests/v2/alu_test.py index 7992ce7f3ca460654a7d577073309116f4471e03..762e414a95f93ea988ed253cfd9d2abe991f8269 100644 --- a/cmake_targets/autotests/v2/alu_test.py +++ b/cmake_targets/autotests/v2/alu_test.py @@ -9,18 +9,24 @@ class alu_test: openair, user, password, log_subdir, - env): - self.epc_machine = epc - self.enb_machine = enb - self.ue_machine = ue - self.openair_dir = openair - self.oai_user = user - self.oai_password = password - self.env = env - - self.task_hss = None - self.task_enb = None - self.task_ue = None + env, + enb_rru = "", + enb_rcc = ""): + self.epc_machine = epc + self.enb_machine = enb + self.ue_machine = ue + self.openair_dir = openair + self.oai_user = user + self.oai_password = password + self.env = env + self.enb_rru_machine = enb_rru + self.enb_rcc_machine = enb_rcc + + self.task_hss = None + self.task_enb = None + self.task_ue = None + self.task_rru_enb = None + self.task_rcc_enb = None self.logdir = openair + '/cmake_targets/autotests/log/' + log_subdir quickshell('mkdir -p ' + self.logdir) @@ -40,6 +46,10 @@ class alu_test: self.task_enb.kill() if self.task_ue != None and self.task_ue.alive(): self.task_ue.kill() + if self.task_rru_enb != None and self.task_rru_enb.alive(): + self.task_rru_enb.kill() + if self.task_rcc_enb != None and self.task_rcc_enb.alive(): + self.task_rcc_enb.kill() ########################################################################## # start_epc @@ -101,8 +111,8 @@ class alu_test: ########################################################################## # compile_enb ########################################################################## - def compile_enb(self, build_arguments): - log("INFO: ALU test: compile softmodem") + def compile_enb(self, build_arguments, log_suffix=""): + log("INFO: ALU test: compile softmodem on " + self.enb_machine) envcomp = list(self.env) envcomp.append('BUILD_ARGUMENTS="' + build_arguments + '"') #we don't care about BUILD_OUTPUT but required (TODO: change that) @@ -120,7 +130,8 @@ class alu_test: self.oai_user, self.oai_password, envcomp, - self.logdir + "/compile_softmodem." + self.enb_machine, + self.logdir + "/compile_softmodem." + log_suffix + \ + self.enb_machine, post_action=post_action) ret = task.wait() if ret != 0: @@ -163,49 +174,107 @@ class alu_test: #os._exit(1) ########################################################################## - # start_bandrich_ue + # start_enb_rru_rcc ########################################################################## - def start_bandrich_ue(self): - log("INFO: ALU test: start bandrich UE") - self.task_ue = Task("actions/start_bandrich.bash", - "start_bandrich", + def start_enb_rru_rcc(self, rru_config_file, rcc_config_file): + #copy wanted configuration files + quickshell("sshpass -p " + self.oai_password + + " scp config/" + rru_config_file + " " + + self.oai_user + "@" + self.enb_rru_machine+":/tmp/enb.conf") + quickshell("sshpass -p " + self.oai_password + + " scp config/" + rcc_config_file + " " + + self.oai_user + "@" + self.enb_rcc_machine+":/tmp/enb.conf") + + #run RRU/RCC softmodem + log("INFO: ALU test: run RRU softmodem with configuration file " + + rru_config_file) + self.task_rru_enb = Task("actions/run_enb.bash", + "run_RRU_softmodem", + self.enb_rru_machine, + self.oai_user, + self.oai_password, + self.env, + self.logdir + "/run_softmodem." + self.enb_rru_machine, + event=self.event) + self.task_rru_enb.waitlog('[RRH] binding to') + log("INFO: ALU test: run RCC softmodem with configuration file " + + rcc_config_file) + self.task_rcc_enb = Task("actions/run_enb.bash", + "run_RCC_softmodem", + self.enb_rcc_machine, + self.oai_user, + self.oai_password, + self.env, + self.logdir + "/run_softmodem." + self.enb_rcc_machine, + event=self.event) + self.task_rcc_enb.waitlog('[BBU] local ip addr') + #wait for RRU and RCC to be connected + self.task_rru_enb.waitlog('devices ok (eNB_thread_asynch_rx)') + + ########################################################################## + # stop_enb_rru_rcc + ########################################################################## + def stop_enb_rru_rcc(self): + log("INFO: ALU test: stop RRU/RCC softmodem") + self.task_rru_enb.sendnow("%c" % 3) + ret = self.task_rru_enb.wait() + if ret != 0: + log("ERROR: ALU test: RRU softmodem failed") + #not sure if we have to quit here or not + #os._exit(1) + self.task_rcc_enb.sendnow("%c" % 3) + ret = self.task_rcc_enb.wait() + if ret != 0: + log("ERROR: ALU test: RCC softmodem failed") + #not sure if we have to quit here or not + #os._exit(1) + + ########################################################################## + # start_ue + ########################################################################## + def start_ue(self, ue): + log("INFO: ALU test: start " + ue + " UE") + self.task_ue = Task("actions/start_" + ue + ".bash", + "start_" + ue, self.ue_machine, self.oai_user, self.oai_password, self.env, - self.logdir + "/start_bandrich." + self.ue_machine, + self.logdir + "/start_" + ue + "." + self.ue_machine, event=self.event) self.task_ue.waitlog("local IP address", event=self.event) self.event.wait() #at this point one task has died or we have the line in the log if self.task_ue.waitlog_state != WAITLOG_SUCCESS: - log("ERROR: ALU test: bandrich UE did not connect") + log("ERROR: ALU test: " + ue + " UE did not connect") raise TestFailed() self.event.clear() - if ( not self.task_enb.alive() or + if ( (self.task_enb != None and not self.task_enb.alive()) or + (self.task_rru_enb!=None and not self.task_rru_enb.alive()) or + (self.task_rcc_enb!=None and not self.task_rcc_enb.alive()) or not self.task_hss.alive() or not self.task_ue.alive()): log("ERROR: ALU test: eNB, HSS or UE task died") raise TestFailed() - #get bandrich UE IP + #get UE IP l = open(self.task_ue.logfile, "r").read() - self.bandrich_ue_ip = re.search("local IP address (.*)\n", l) \ - .groups()[0] - log("INFO: ALU test: bandrich UE IP address: " + self.bandrich_ue_ip) + self.ue_ip = re.search("local IP address (.*)\n", l) \ + .groups()[0] + log("INFO: ALU test: " + ue + " UE IP address: " + self.ue_ip) ########################################################################## - # stop_bandrich_ue + # stop_ue ########################################################################## - def stop_bandrich_ue(self): - log("INFO: ALU test: stop bandrich UE") + def stop_ue(self, ue): + log("INFO: ALU test: stop " + ue + " UE") self.task_ue.sendnow("%c" % 3) ret = self.task_ue.wait() if ret != 0: - log("ERROR: ALU test: task bandrich UE failed") + log("ERROR: ALU test: task " + ue + " UE failed") #not sure if we have to quit here or not #os._exit(1) @@ -250,14 +319,20 @@ class alu_test: self.event.wait() log("DEBUG: event.wait() done") - if ( not self.task_enb.alive() or + if ( (self.task_enb != None and not self.task_enb.alive()) or + (self.task_rru_enb!=None and not self.task_rru_enb.alive()) or + (self.task_rcc_enb!=None and not self.task_rcc_enb.alive()) or not self.task_hss.alive() or not self.task_ue.alive()): log("ERROR: unexpected task exited, test failed, kill all") if task_traffic_client.alive(): task_traffic_client.kill() - if self.task_enb.alive(): + if (self.task_enb != None and self.task_enb.alive()): self.task_enb.kill() + if (self.task_rru_enb != None and self.task_rru_enb.alive()): + self.task_rru_enb.kill() + if (self.task_rcc_enb != None and self.task_rcc_enb.alive()): + self.task_rcc_enb.kill() if self.task_ue.alive(): self.task_ue.kill() @@ -277,7 +352,9 @@ class alu_test: self.event.clear() - if ( not self.task_enb.alive() or + if ( (self.task_enb != None and not self.task_enb.alive()) or + (self.task_rru_enb!=None and not self.task_rru_enb.alive()) or + (self.task_rcc_enb!=None and not self.task_rcc_enb.alive()) or not self.task_hss.alive() or not self.task_ue.alive()): log("ERROR: ALU test: eNB, HSS or UE task died") @@ -286,47 +363,47 @@ class alu_test: ########################################################################## # dl_tcp ########################################################################## - def dl_tcp(self): - self._do_traffic("bandrich downlink TCP", - "server_tcp", self.ue_machine, self.bandrich_ue_ip, + def dl_tcp(self, ue): + self._do_traffic(ue + " downlink TCP", + "server_tcp", self.ue_machine, self.ue_ip, "client_tcp", self.epc_machine, "Server listening on TCP port 5001", - "bandrich_downlink_tcp_server", - "bandrich_downlink_tcp_client") + ue + "_downlink_tcp_server", + ue + "_downlink_tcp_client") ########################################################################## # ul_tcp ########################################################################## - def ul_tcp(self): - self._do_traffic("bandrich uplink TCP", + def ul_tcp(self, ue): + self._do_traffic(ue + " uplink TCP", "server_tcp", self.epc_machine, "192.172.0.1", "client_tcp", self.ue_machine, "Server listening on TCP port 5001", - "bandrich_uplink_tcp_server", - "bandrich_uplink_tcp_client") + ue + "_uplink_tcp_server", + ue + "_uplink_tcp_client") ########################################################################## # dl_udp ########################################################################## - def dl_udp(self, bandwidth): - self._do_traffic("bandrich downlink UDP", - "server_udp", self.ue_machine, self.bandrich_ue_ip, + def dl_udp(self, ue, bandwidth): + self._do_traffic(ue + " downlink UDP", + "server_udp", self.ue_machine, self.ue_ip, "client_udp", self.epc_machine, "Server listening on UDP port 5001", - "bandrich_downlink_udp_server", - "bandrich_downlink_udp_client", + ue + "_downlink_udp_server", + ue + "_downlink_udp_client", udp_bandwidth=bandwidth) ########################################################################## # ul_udp ########################################################################## - def ul_udp(self, bandwidth): - self._do_traffic("bandrich uplink UDP", + def ul_udp(self, ue, bandwidth): + self._do_traffic(ue + " uplink UDP", "server_udp", self.epc_machine, "192.172.0.1", "client_udp", self.ue_machine, "Server listening on UDP port 5001", - "bandrich_uplink_udp_server", - "bandrich_uplink_udp_client", + ue + "_uplink_udp_server", + ue + "_uplink_udp_client", udp_bandwidth=bandwidth) ############################################################################## @@ -334,22 +411,72 @@ class alu_test: ############################################################################## def run_b210_alu(tests, openair_dir, oai_user, oai_password, env): - if not do_tests(tests['b210']['alu']): - return - - #compile eNB - alu = alu_test(epc='amerique', enb='hutch', ue='stevens', - openair=openair_dir, - user=oai_user, password=oai_password, - log_subdir='enb_tests/b210_alu/compile_enb', - env=env) + #compile eNB (two cases: one for FDD and one for TDD) + + if do_tests(tests['b210']['alu']['fdd']): + alu = alu_test(epc='amerique', enb='hutch', ue='stevens', + openair=openair_dir, + user=oai_user, password=oai_password, + log_subdir='enb_tests/b210_alu/compile_enb_fdd', + env=env) + + try: + alu.compile_enb("--eNB -w USRP -x -c --disable-cpu-affinity") + except BaseException, e: + log("ERROR: ALU test failed: eNB compilation failed: " + str(e)) + return + + if do_tests(tests['b210']['alu']['tdd']): + alu = alu_test(epc='amerique', enb='calisson', ue='mozart', + openair=openair_dir, + user=oai_user, password=oai_password, + log_subdir='enb_tests/b210_alu/compile_enb_tdd', + env=env) + + try: + alu.compile_enb("--eNB -w USRP -x -c --disable-cpu-affinity") + except BaseException, e: + log("ERROR: ALU test failed: eNB compilation failed: " + str(e)) + return + + #compile RRU/RCC eNB + + if do_tests(tests['remote b210']['alu']['fdd']): + #RRU + alu = alu_test(epc='amerique', ue='stevens', + openair=openair_dir, + user=oai_user, password=oai_password, + log_subdir='enb_tests/remote_b210_alu/compile_enb_rru', + env=env, + #hack: set 'enb' to reuse 'compile_enb' + enb = 'superserver', + enb_rru = 'superserver', enb_rcc = 'starsky') + + try: + alu.compile_enb("--eNB -x -c -w USRP -t ETHERNET", + log_suffix='rru.') + except BaseException, e: + log("ERROR: ALU test failed: RRU eNB compilation failed: "+str(e)) + return + + #RCC + alu = alu_test(epc='amerique', ue='stevens', + openair=openair_dir, + user=oai_user, password=oai_password, + log_subdir='enb_tests/remote_b210_alu/compile_enb_rcc', + env=env, + #hack: set 'enb' to reuse 'compile_enb' + enb = 'starsky', + enb_rru = 'superserver', enb_rcc = 'starsky') + + try: + alu.compile_enb("--eNB -w None -t ETHERNET", + log_suffix='rcc.') + except BaseException, e: + log("ERROR: ALU test failed: RCC eNB compilation failed: "+str(e)) + return - try: - alu.compile_enb("--eNB -w USRP -x -c --disable-cpu-affinity") - except BaseException, e: - log("ERROR: ALU test failed: eNB compilation failed: " + str(e)) - return #run tests @@ -361,29 +488,64 @@ def run_b210_alu(tests, openair_dir, oai_user, oai_password, env): "10" : "15M", "20" : "15M" } - for bw in ('5', '10', '20'): - if do_tests(tests['b210']['alu'][bw]): - log("INFO: ALU test: run tests for bandwidth " + bw + " MHz") - ctest = tests['b210']['alu'][bw] - alu = alu_test(epc='amerique', enb='hutch', ue='stevens', - openair=openair_dir, - user=oai_user, password=oai_password, - log_subdir='enb_tests/b210_alu/' + bw, - env=env) - try: - alu.start_epc() - alu.start_enb("enb.band7.tm1.usrpb210." + bw + "MHz.conf") - if do_tests(ctest['bandrich']): - alu.start_bandrich_ue() - if do_tests(ctest['bandrich']['tcp']['dl']): alu.dl_tcp() - if do_tests(ctest['bandrich']['tcp']['ul']): alu.ul_tcp() - if do_tests(ctest['bandrich']['udp']['dl']): - alu.dl_udp(udp_dl_bandwidth[bw]) - if do_tests(ctest['bandrich']['udp']['ul']): - alu.ul_udp(udp_ul_bandwidth[bw]) - alu.stop_bandrich_ue() - alu.stop_enb() - alu.stop_epc() - except BaseException, e: - log("ERROR: ALU test failed: " + str(e)) - alu.finish() + ue_machine = { "fdd" : "stevens", + "tdd" : "mozart" } + + enb_machine = { "fdd" : "hutch", + "tdd" : "calisson" } + + band = { "fdd" : "7", + "tdd" : "38" } + + for mode in ('fdd', 'tdd'): + for bw in ('5', '10', '20'): + if do_tests(tests['b210']['alu'][mode][bw]): + log("INFO: ALU test: run tests for bandwidth " + bw + " MHz") + ctest = tests['b210']['alu'][mode][bw] + alu = alu_test(epc='amerique', enb=enb_machine[mode], ue=ue_machine[mode], + openair=openair_dir, + user=oai_user, password=oai_password, + log_subdir='enb_tests/b210_alu/' + mode + "/" + bw, + env=env) + try: + alu.start_epc() + alu.start_enb("enb.band" + band[mode] + ".tm1.usrpb210." + mode + "." + bw + "MHz.conf") + for ue in ('bandrich', '3276'): + if ue in ctest and do_tests(ctest[ue]): + alu.start_ue(ue) + if do_tests(ctest[ue]['tcp']['dl']): alu.dl_tcp(ue) + if do_tests(ctest[ue]['tcp']['ul']): alu.ul_tcp(ue) + if do_tests(ctest[ue]['udp']['dl']): alu.dl_udp(ue, udp_dl_bandwidth[bw]) + if do_tests(ctest[ue]['udp']['ul']): alu.ul_udp(ue, udp_ul_bandwidth[bw]) + alu.stop_ue(ue) + alu.stop_enb() + alu.stop_epc() + except BaseException, e: + log("ERROR: ALU test failed: " + str(e)) + alu.finish() + if do_tests(tests['remote b210']['alu'][mode][bw]): + log("INFO: ALU test: run RRU/RCC tests for bandwidth " + bw + " MHz") + ctest = tests['remote b210']['alu'][mode][bw] + alu = alu_test(epc='amerique', enb='', ue=ue_machine[mode], + openair=openair_dir, + user=oai_user, password=oai_password, + log_subdir='enb_tests/remote_b210_alu/' + bw, + env=env, + enb_rru='superserver', enb_rcc='starsky') + try: + alu.start_epc() + alu.start_enb_rru_rcc("rru.band7.tm1.if4p5." + bw + "MHz.udp.usrpb210.conf", + "rcc.band7.tm1.if4p5." + bw + "MHz.conf") + for ue in ('bandrich', '3276'): + if ue in ctest and do_tests(ctest[ue]): + alu.start_ue(ue) + if do_tests(ctest[ue]['tcp']['dl']): alu.dl_tcp(ue) + if do_tests(ctest[ue]['tcp']['ul']): alu.ul_tcp(ue) + if do_tests(ctest[ue]['udp']['dl']): alu.dl_udp(ue, udp_dl_bandwidth[bw]) + if do_tests(ctest[ue]['udp']['ul']): alu.ul_udp(ue, udp_ul_bandwidth[bw]) + alu.stop_ue(ue) + alu.stop_enb_rru_rcc() + alu.stop_epc() + except BaseException, e: + log("ERROR: ALU test failed: " + str(e)) + alu.finish() diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf new file mode 100644 index 0000000000000000000000000000000000000000..c25b954e1ab532de744b65bed211876a86cabd7e --- /dev/null +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf @@ -0,0 +1,175 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2580000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -24; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf new file mode 100644 index 0000000000000000000000000000000000000000..0773f9c267fd5e2675ce54c7896db50bce8b74cc --- /dev/null +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf @@ -0,0 +1,175 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2580000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -24; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf new file mode 100644 index 0000000000000000000000000000000000000000..024be3b77535bde64d8c6d346509cf8e6948de6b --- /dev/null +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf @@ -0,0 +1,175 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2580000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -24; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.10MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf similarity index 100% rename from cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.10MHz.conf rename to cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.20MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf similarity index 100% rename from cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.20MHz.conf rename to cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.5MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf similarity index 100% rename from cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.5MHz.conf rename to cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf new file mode 100644 index 0000000000000000000000000000000000000000..81eed5f4b10946477df799fd0820e51ea2ffb71a --- /dev/null +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.18/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.18/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth1"; + remote_address = "10.10.10.157"; + local_address = "10.10.10.18"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "udp_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + if_compression = "alaw"; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf new file mode 100644 index 0000000000000000000000000000000000000000..4b4190f8ce980cf107f62bd76eab8a9ca9ecf1da --- /dev/null +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.18/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.18/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth1"; + remote_address = "10.10.10.157"; + local_address = "10.10.10.18"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "udp_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + if_compression = "alaw"; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf new file mode 100644 index 0000000000000000000000000000000000000000..99b9a66226f0b1d5bc821f632d59636e604fc4f0 --- /dev/null +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.18/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.18/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth1"; + remote_address = "10.10.10.157"; + local_address = "10.10.10.18"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "udp_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + if_compression = "alaw"; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf new file mode 100644 index 0000000000000000000000000000000000000000..4cc40b6d84139da98b1250b62ba480bce60406f0 --- /dev/null +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf @@ -0,0 +1,194 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth3"; + remote_address = "10.10.10.18"; + local_address = "10.10.10.157"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "udp_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + if_compression = "alaw"; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf new file mode 100644 index 0000000000000000000000000000000000000000..787cedb18d9972ef05e3d5d0f75074977cfc92e5 --- /dev/null +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf @@ -0,0 +1,194 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth3"; + remote_address = "10.10.10.18"; + local_address = "10.10.10.157"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "udp_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + if_compression = "alaw"; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf new file mode 100644 index 0000000000000000000000000000000000000000..d9d46bf9446cef80a3fe8dd0a3c1eaa47d245972 --- /dev/null +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf @@ -0,0 +1,194 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth3"; + remote_address = "10.10.10.18"; + local_address = "10.10.10.157"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "udp_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + if_compression = "alaw"; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/cmake_targets/autotests/v2/main.py b/cmake_targets/autotests/v2/main.py index 6cf3b97c3608579706058f0ba465c84f86fbb734..da38432dbc270f9b208135191bd6a3df6d9a357d 100644 --- a/cmake_targets/autotests/v2/main.py +++ b/cmake_targets/autotests/v2/main.py @@ -280,65 +280,45 @@ machine_list.wait_all_free() # run eNB softmodem tests # ############################################################################## -tests = { - 'b210' : { - 'alu' : { - '5' : { - 'bandrich' : { - 'tcp' : { 'ul': False, 'dl' : False }, - 'udp' : { 'ul': False, 'dl' : False }}, - 'sony' : { - 'tcp' : { 'ul': False, 'dl' : False }, - 'udp' : { 'ul': False, 'dl' : False }}}, - '10' : { - 'bandrich' : { - 'tcp' : { 'ul': False, 'dl' : False }, - 'udp' : { 'ul': False, 'dl' : False }}, - 'sony' : { - 'tcp' : { 'ul': False, 'dl' : False }, - 'udp' : { 'ul': False, 'dl' : False }}}, - '20' : { - 'bandrich' : { - 'tcp' : { 'ul': False, 'dl' : False }, - 'udp' : { 'ul': False, 'dl' : False }}, - 'sony' : { - 'tcp' : { 'ul': False, 'dl' : False }, - 'udp' : { 'ul': False, 'dl' : False }}}}, - 'openair-cn' : {} - }, - 'x310' : { - 'alu' : {}, - 'openair-cn' : {} - }, - 'exmimo2' : { - 'alu' : {}, - 'openair-cn' : {} - } -} +tests = {} +for a in { 'b210', 'remote b210', 'x310', 'exmimo2' }: + tests[a] = {} + for b in { 'alu', 'openair-cn' }: + tests[a][b] = {} + for c in { 'fdd', 'tdd' }: + tests[a][b][c] = {} + for d in { '5', '10', '20' }: + tests[a][b][c][d] = {} + for e in { 'bandrich', 'sony', '3276' }: + tests[a][b][c][d][e] = {} + for f in { 'tcp', 'udp' }: + tests[a][b][c][d][e][f] = {} + for g in { 'dl', 'ul' }: + tests[a][b][c][d][e][f][g] = False todo_tests_ids = [] for test in todo_tests: todo_tests_ids.append(test.get('id')) for test in todo_tests_ids: - if test=='015500':tests['b210']['alu'][ '5']['bandrich']['udp']['ul']=True - if test=='015501':tests['b210']['alu']['10']['bandrich']['udp']['ul']=True - if test=='015502':tests['b210']['alu']['20']['bandrich']['udp']['ul']=True - if test=='015503':tests['b210']['alu'][ '5']['bandrich']['udp']['dl']=True - if test=='015504':tests['b210']['alu']['10']['bandrich']['udp']['dl']=True - if test=='015505':tests['b210']['alu']['20']['bandrich']['udp']['dl']=True + if test=='015500':tests['b210']['alu']['fdd'][ '5']['bandrich']['udp']['ul']=True + if test=='015501':tests['b210']['alu']['fdd']['10']['bandrich']['udp']['ul']=True + if test=='015502':tests['b210']['alu']['fdd']['20']['bandrich']['udp']['ul']=True + if test=='015503':tests['b210']['alu']['fdd'][ '5']['bandrich']['udp']['dl']=True + if test=='015504':tests['b210']['alu']['fdd']['10']['bandrich']['udp']['dl']=True + if test=='015505':tests['b210']['alu']['fdd']['20']['bandrich']['udp']['dl']=True if test=='015506':log('WARNING: skip test ' + test) #TODO if test=='015507':log('WARNING: skip test ' + test) #TODO if test=='015508':log('WARNING: skip test ' + test) #TODO if test=='015509':log('WARNING: skip test ' + test) #TODO if test=='015510':log('WARNING: skip test ' + test) #TODO if test=='015511':log('WARNING: skip test ' + test) #TODO - if test=='015512':tests['b210']['alu'][ '5']['bandrich']['tcp']['ul']=True - if test=='015513':tests['b210']['alu']['10']['bandrich']['tcp']['ul']=True - if test=='015514':tests['b210']['alu']['20']['bandrich']['tcp']['ul']=True - if test=='015515':tests['b210']['alu'][ '5']['bandrich']['tcp']['dl']=True - if test=='015516':tests['b210']['alu']['10']['bandrich']['tcp']['dl']=True - if test=='015517':tests['b210']['alu']['20']['bandrich']['tcp']['dl']=True + if test=='015512':tests['b210']['alu']['fdd'][ '5']['bandrich']['tcp']['ul']=True + if test=='015513':tests['b210']['alu']['fdd']['10']['bandrich']['tcp']['ul']=True + if test=='015514':tests['b210']['alu']['fdd']['20']['bandrich']['tcp']['ul']=True + if test=='015515':tests['b210']['alu']['fdd'][ '5']['bandrich']['tcp']['dl']=True + if test=='015516':tests['b210']['alu']['fdd']['10']['bandrich']['tcp']['dl']=True + if test=='015517':tests['b210']['alu']['fdd']['20']['bandrich']['tcp']['dl']=True if test=='015518':log('WARNING: skip test ' + test) #TODO if test=='015519':log('WARNING: skip test ' + test) #TODO if test=='015520':log('WARNING: skip test ' + test) #TODO @@ -427,6 +407,19 @@ for test in todo_tests_ids: if test=='017504':log('WARNING: skip test ' + test) #TODO if test=='017505':log('WARNING: skip test ' + test) #TODO + if test=='017600':tests['remote b210']['alu']['fdd'][ '5']['bandrich']['udp']['ul']=True + if test=='017601':tests['remote b210']['alu']['fdd']['10']['bandrich']['udp']['ul']=True + if test=='017602':tests['remote b210']['alu']['fdd']['20']['bandrich']['udp']['ul']=True + if test=='017603':tests['remote b210']['alu']['fdd'][ '5']['bandrich']['udp']['dl']=True + if test=='017604':tests['remote b210']['alu']['fdd']['10']['bandrich']['udp']['dl']=True + if test=='017605':tests['remote b210']['alu']['fdd']['20']['bandrich']['udp']['dl']=True + if test=='017606':tests['remote b210']['alu']['fdd'][ '5']['bandrich']['tcp']['ul']=True + if test=='017607':tests['remote b210']['alu']['fdd']['10']['bandrich']['tcp']['ul']=True + if test=='017608':tests['remote b210']['alu']['fdd']['20']['bandrich']['tcp']['ul']=True + if test=='017609':tests['remote b210']['alu']['fdd'][ '5']['bandrich']['tcp']['dl']=True + if test=='017610':tests['remote b210']['alu']['fdd']['10']['bandrich']['tcp']['dl']=True + if test=='017611':tests['remote b210']['alu']['fdd']['20']['bandrich']['tcp']['dl']=True + if test=='018000':log('WARNING: skip test ' + test) #TODO if test=='018001':log('WARNING: skip test ' + test) #TODO if test=='018002':log('WARNING: skip test ' + test) #TODO @@ -441,6 +434,31 @@ for test in todo_tests_ids: if test=='018504':log('WARNING: skip test ' + test) #TODO if test=='018505':log('WARNING: skip test ' + test) #TODO + if test=='018600':tests['b210']['alu']['tdd'][ '5']['3276']['udp']['ul']=True + if test=='018601':tests['b210']['alu']['tdd']['10']['3276']['udp']['ul']=True + if test=='018602':tests['b210']['alu']['tdd']['20']['3276']['udp']['ul']=True + if test=='018603':tests['b210']['alu']['tdd'][ '5']['3276']['udp']['dl']=True + if test=='018604':tests['b210']['alu']['tdd']['10']['3276']['udp']['dl']=True + if test=='018605':tests['b210']['alu']['tdd']['20']['3276']['udp']['dl']=True + if test=='018606':log('WARNING: skip test ' + test) #TODO + if test=='018607':log('WARNING: skip test ' + test) #TODO + if test=='018608':log('WARNING: skip test ' + test) #TODO + if test=='018609':log('WARNING: skip test ' + test) #TODO + if test=='018610':log('WARNING: skip test ' + test) #TODO + if test=='018611':log('WARNING: skip test ' + test) #TODO + if test=='018612':tests['b210']['alu']['tdd'][ '5']['3276']['tcp']['ul']=True + if test=='018613':tests['b210']['alu']['tdd']['10']['3276']['tcp']['ul']=True + if test=='018614':tests['b210']['alu']['tdd']['20']['3276']['tcp']['ul']=True + if test=='018615':tests['b210']['alu']['tdd'][ '5']['3276']['tcp']['dl']=True + if test=='018616':tests['b210']['alu']['tdd']['10']['3276']['tcp']['dl']=True + if test=='018617':tests['b210']['alu']['tdd']['20']['3276']['tcp']['dl']=True + if test=='018618':log('WARNING: skip test ' + test) #TODO + if test=='018619':log('WARNING: skip test ' + test) #TODO + if test=='018620':log('WARNING: skip test ' + test) #TODO + if test=='018621':log('WARNING: skip test ' + test) #TODO + if test=='018622':log('WARNING: skip test ' + test) #TODO + if test=='018623':log('WARNING: skip test ' + test) #TODO + if test=='025500':log('WARNING: skip test ' + test) #TODO if test=='025501':log('WARNING: skip test ' + test) #TODO if test=='025502':log('WARNING: skip test ' + test) #TODO diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 2272a338bef1ec8edb476ed657d9b5a2b6670712..93a7ac073ee88a9d2b359025a4c33c743ce19efc 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -33,6 +33,13 @@ ORIGIN_PATH=$PWD THIS_SCRIPT_PATH=$(dirname $(readlink -f $0)) source $THIS_SCRIPT_PATH/tools/build_helper +# set environment variables (OPENAIR_HOME, ...) +set_openair_env + +#variables for UE data generation +gen_nvram_path=$OPENAIR_DIR/targets/bin +conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf + MSC_GEN="False" XFORMS="True" FLEXRAN_AGENT_SB_IF="True" @@ -41,7 +48,7 @@ VCD_TIMING="False" DEADLINE_SCHEDULER_FLAG_USER="False" FORCE_DEADLINE_SCHEDULER_FLAG_USER="" CPU_AFFINITY_FLAG_USER="False" #Only valid when lowlatecy flag is set to False -REL="Rel10" +REL="Rel14" HW="None" TP="None" NOS1=0 @@ -55,19 +62,21 @@ T_TRACER="False" DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="" UE_AUTOTEST_TRACE="False" +BUILD_ECLIPSE=0 +CMAKE_CMD='cmake' trap handle_ctrl_c INT function print_help() { - echo_info ' + echo_info " This program installs OpenAirInterface Software You should have ubuntu 14.xx, updated, and the Linux kernel >= 3.14 Options -h This help -c | --clean - Erase all files to make a rebuild from start" + Erase all files to make a rebuild from start -C | --clean-all - Erase all files made by previous compilations, installations" + Erase all files made by previous compilations, installations --clean-kernel Erase previously installed features in kernel: iptables, drivers, ... -I | --install-external-packages @@ -82,14 +91,19 @@ Options --eNB Makes the LTE softmodem --UE - Makes the UE specific parts (ue_ip, usim, nvram) + Makes the UE specific parts (ue_ip, usim, nvram) from the given configuration file +--UE-conf-nvram [configuration file] + Specify conf_nvram_path (default \"$conf_nvram_path\") +--UE-gen-nvram [output path] + Specify gen_nvram_path (default \"$gen_nvram_path\") --RRH Makes the RRH -a | --agent Enables agent for software-defined control of the eNB -r | --3gpp-release - default is Rel10, + default is Rel14, Rel8 limits the implementation to 3GPP Release 8 version + Rel10 limits the implementation to 3GPP Release 10 version -w | --hardware EXMIMO, USRP, BLADERF, ETHERNET, LMSSDR, None (Default) Adds this RF board support (in external packages installation and in compilation) @@ -97,7 +111,7 @@ Options ETHERNET , None Adds this trasport protocol support in compilation --oaisim - Makes the oaisim simulator. Hardware will be defaulted to "None". + Makes the oaisim simulator. Hardware will be defaulted to \"None\". --phy_simulators Makes the unitary tests Layer 1 simulators --core_simulators @@ -133,6 +147,8 @@ Options Disable HW dependency during installation --ue-autotest-trace Enable specific traces for UE autotest framework +--build-eclipse + Build eclipse project files. Paths are auto corrected by fixprj.sh Usage (first build): oaisim (eNB + UE): ./build_oai -I --oaisim -x --install-system-files Eurecom EXMIMO + COTS UE : ./build_oai -I --eNB -x --install-system-files @@ -140,11 +156,12 @@ Usage (first build): Usage (Regular): oaisim : ./build_oai --oaisim -x Eurecom EXMIMO + OAI ENB : ./build_oai --eNB -x - NI/ETTUS B201 + OAI ENB : ./build_oai --eNB -x -w USRP' + NI/ETTUS B201 + OAI ENB : ./build_oai --eNB -x -w USRP" } function main() { + until [ -z "$1" ] do case "$1" in @@ -170,6 +187,7 @@ function main() { GDB=1 CMAKE_BUILD_TYPE="Debug" echo_info "Will Compile with gdb symbols and disable compiler optimization" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug" shift;; --eNB) eNB=1 @@ -183,6 +201,12 @@ function main() { UE=1 echo_info "Will compile UE" shift;; + --UE-conf-nvram) + conf_nvram_path=$(readlink -f "$1") + shift 2;; + --UE-gen-nvram) + gen_nvram_path=$(readlink -f $2) + shift 2;; --RRH) RRH=1 echo_info "Will compile RRH" @@ -292,6 +316,15 @@ function main() { UE_AUTOTEST_TRACE="True" echo_info "Enabling autotest specific trace for UE" shift 1;; + --uhd-images-dir) + UHD_IMAGES_DIR=$2 + echo_info "Downloading UHD images in the indicated location" + shift 2;; + --build-eclipse) + BUILD_ECLIPSE=1 + CMAKE_CMD="$CMAKE_CMD"' -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=TRUE -G"Eclipse CDT4 - Unix Makefiles"' + echo_info "Enabling build eclipse project support" + shift 1;; -h | --help) print_help exit 1;; @@ -302,6 +335,9 @@ function main() { esac done + CMAKE_CMD="$CMAKE_CMD .." + echo_info "CMAKE_CMD=$CMAKE_CMD" + ######################################################### # check validity of HW and TP parameters for RRH and eNB ######################################################### @@ -362,13 +398,16 @@ function main() { echo_info "Flags for Deadline scheduler: $DEADLINE_SCHEDULER_FLAG_USER" echo_info "Flags for CPU Affinity: $CPU_AFFINITY_FLAG_USER" + if [ -n "$UHD_IMAGES_DIR" ] && [ -z "$INSTALL_EXTERNAL" ]; then + echo_error "UHD images download settings will not be applied without -I present" + exit + fi ############################################ # setting and printing OAI envs, we should check here ############################################ echo_info "2. Setting the OAI PATHS ..." - set_openair_env cecho "OPENAIR_DIR = $OPENAIR_DIR" $green # for conf files copy in this bash script @@ -399,7 +438,7 @@ function main() { echo_info "installing packages for USRP support" check_install_usrp_uhd_driver if [ ! "$DISABLE_HARDWARE_DEPENDENCY" == "True" ]; then - install_usrp_uhd_driver + install_usrp_uhd_driver $UHD_IMAGES_DIR fi fi if [ "$HW" == "OAI_BLADERF" ] ; then @@ -472,7 +511,7 @@ function main() { fi echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$lte_build_dir/build - cmake .. + eval $CMAKE_CMD fi if [ "$eNB" = "1" -o "$UE" = "1" ] ; then @@ -501,7 +540,7 @@ function main() { # mkdir -p $DIR/at_commands/build # cd $DIR/at_commands/build -# cmake .. +# eval $CMAKE_CMD # compilations \ # at_commands at_nas_ue \ # at_nas_ue $dbin/at_nas_ue @@ -510,22 +549,24 @@ function main() { mkdir -p $DIR/nas_sim_tools/build cd $DIR/nas_sim_tools/build - cmake .. + eval $CMAKE_CMD compilations \ nas_sim_tools usim \ usim $dbin/usim compilations \ nas_sim_tools nvram \ nvram $dbin/nvram + compilations \ + nas_sim_tools conf2uedata \ + conf2uedata $dbin/conf2uedata # generate USIM data - if [ -f $dbin/nvram ]; then - install_nas_tools $dbin $dconf + if [ -f $dbin/conf2uedata ]; then + install_nas_tools $conf_nvram_path $gen_nvram_path echo_info "Copying UE specific part to $DIR/$lte_build_dir/build" - cp -Rvf $dbin/.ue_emm.nvram $DIR/$lte_build_dir/build - cp -Rvf $dbin/.ue.nvram $DIR/$lte_build_dir/build - cp -Rvf $dbin/.usim.nvram $DIR/$lte_build_dir/build - + cp -Rvf $dbin/.ue_emm.nvram0 $DIR/$lte_build_dir/build + cp -Rvf $dbin/.ue.nvram0 $DIR/$lte_build_dir/build + cp -Rvf $dbin/.usim.nvram0 $DIR/$lte_build_dir/build else echo_warning "not generated UE NAS files: binaries not found" fi @@ -537,13 +578,13 @@ function main() { mkdir -p build cd build rm -f *sim - cmake .. + eval $CMAKE_CMD fi if [ "$SIMUS_PHY" = "1" ] ; then # lte unitary simulators compilation echo_info "Compiling unitary tests simulators" - simlist="dlsim ulsim pucchsim prachsim pdcchsim pbchsim mbmssim" + simlist="dlsim_tm4 dlsim ulsim pucchsim prachsim pdcchsim pbchsim mbmssim" for f in $simlist ; do compilations \ lte-simulators $f \ @@ -615,7 +656,7 @@ function main() { [ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build mkdir -p $DIR/$oaisim_build_dir/build cd $DIR/$oaisim_build_dir/build - cmake .. + eval $CMAKE_CMD compilations \ $oaisim_build_dir $oaisim_exec \ $oaisim_exec $dbin/$oaisim_exec.$REL @@ -626,7 +667,7 @@ function main() { echo_info "Compiling at_nas_ue" mkdir -p $DIR/at_commands/build cd $DIR/at_commands/build - cmake .. + eval $CMAKE_CMD compilations \ at_commands at_nas_ue \ at_nas_ue $dbin/at_nas_ue @@ -640,17 +681,20 @@ function main() { [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build mkdir -p $DIR/nas_sim_tools/build cd $DIR/nas_sim_tools/build - cmake .. + eval $CMAKE_CMD compilations \ nas_sim_tools usim \ usim $dbin/usim compilations \ nas_sim_tools nvram \ nvram $dbin/nvram + compilations \ + nas_sim_tools conf2uedata \ + conf2uedata $dbin/conf2uedata # generate USIM data - if [ -f $dbin/nvram ]; then - install_nas_tools $dbin $dconf + if [ -f $dbin/conf2uedata ]; then + install_nas_tools $conf_nvram_path $gen_nvram_path else echo_warning "not generated UE NAS files: binaries not found" fi @@ -675,8 +719,8 @@ function main() { compilations \ $oaisim_build_dir oai_eth_transpro \ liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL - ln -s liboai_eth_transpro.so liboai_transpro.so - ln -s $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so + ln -sf liboai_eth_transpro.so liboai_transpro.so + ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so echo_info "liboai_transpro.so is linked with ETHERNET library" fi @@ -694,7 +738,7 @@ function main() { #[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build #mkdir -p $DIR/oaisim_mme_build_oai/build #cd $DIR/oaisim_mme_build_oai/build - #cmake .. + #eval $CMAKE_CMD #compilations \ # oaisim_mme_build_oai oaisim_mme \ # oaisim_mme $dbin/oaisim_mme.$REL @@ -724,7 +768,7 @@ function main() { echo "set ( T_TRACER $T_TRACER )" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$rrh_build_dir/build - cmake .. + eval $CMAKE_CMD compilations \ rrh_gw rrh_gw \ rrh_gw $dbin/rrh_gw @@ -733,28 +777,27 @@ function main() { # build RF device and transport protocol libraries ##################################### - if [ "$eNB" = "1" -o "$RRH" = "1" ] ; then + if [ "$eNB" = "1" -o "$UE" = "1" -o "$RRH" = "1" ] ; then - if [ "$eNB" = "1" ] ; then + if [ "$eNB" = "1" -o "$UE" = "1" ] ; then build_dir=$lte_build_dir else build_dir=$rrh_build_dir fi - # build RF device libraries (currently EXMIMO is not complied with the rest of HW targets) + # build RF device libraries if [ "$HW" != "None" ] ; then rm -f liboai_device.so rm -f $dbin/liboai_device.so - # link liboai_device.so with the selected RF device library if [ "$HW" == "EXMIMO" ] ; then - - #add exmimo compilation - #TODO EXMIMO library support compilations \ $build_dir oai_exmimodevif \ liboai_exmimodevif.so $dbin/liboai_exmimodevif.so.$REL + + ln -sf liboai_exmimodevif.so liboai_device.so + ln -sf $dbin/liboai_exmimodevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to EXMIMO device library" elif [ "$HW" == "OAI_USRP" ] ; then if [ -d "/usr/include/uhd" ] ; then @@ -763,8 +806,8 @@ function main() { liboai_usrpdevif.so $dbin/liboai_usrpdevif.so.$REL fi - ln -s liboai_usrpdevif.so liboai_device.so - ln -s $dbin/liboai_usrpdevif.so.$REL $dbin/liboai_device.so + ln -sf liboai_usrpdevif.so liboai_device.so + ln -sf $dbin/liboai_usrpdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to USRP device library" elif [ "$HW" == "OAI_BLADERF" ] ; then if [ -f "/usr/include/libbladeRF.h" ] ; then @@ -773,8 +816,8 @@ function main() { liboai_bladerfdevif.so $dbin/liboai_bladerfdevif.so.$REL fi - ln -s liboai_bladerfdevif.so liboai_device.so - ln -s $dbin/liboai_bladerfdevif.so.$REL $dbin/liboai_device.so + ln -sf liboai_bladerfdevif.so liboai_device.so + ln -sf $dbin/liboai_bladerfdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to BLADERF device library" elif [ "$HW" == "OAI_LMSSDR" ] ; then # if [ -f "/usr/include/libbladeRF.h" ] ; then @@ -783,8 +826,8 @@ function main() { liboai_lmssdrdevif.so $dbin/liboai_lmssdrdevif.so.$REL # fi - ln -s liboai_lmssdrdevif.so liboai_device.so - ln -s $dbin/liboai_lmssdrdevif.so.$REL $dbin/liboai_device.so + ln -sf liboai_lmssdrdevif.so liboai_device.so + ln -sf $dbin/liboai_lmssdrdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to LMSSDR device library" else echo_info "liboai_device.so is not linked to any device library" @@ -800,8 +843,8 @@ function main() { compilations \ $build_dir oai_eth_transpro \ liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL - ln -s liboai_eth_transpro.so liboai_transpro.so - ln -s $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so + ln -sf liboai_eth_transpro.so liboai_transpro.so + ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so echo_info "liboai_transpro.so is linked with ETHERNET library" fi fi @@ -819,7 +862,7 @@ fi [ "$CLEAN" = "1" ] && rm -rf $OPENAIR_DIR/cmake_targets/doxygen/build mkdir -p $OPENAIR_DIR/cmake_targets/doxygen/build cd $OPENAIR_DIR/cmake_targets/doxygen/build - cmake .. + eval $CMAKE_CMD make doc ) >& $doxygen_log fi diff --git a/cmake_targets/build_ue b/cmake_targets/build_ue new file mode 100644 index 0000000000000000000000000000000000000000..9d9ca839d10c0164f038a8b6eb4a79f772e01d70 --- /dev/null +++ b/cmake_targets/build_ue @@ -0,0 +1,6 @@ +#!/bin/bash +#sudo ./build_oai -c -C -I --install-optional-packages --install-system-files --UE -w USRP -V +#sudo ./build_oai -c -C -I --install-optional-packages --UE -w USRP -V +#sudo ./build_oai -c -C --UE -w USRP -V +sudo ./build_oai -c -C --UE -w USRP +#sudo ./build_oai -c -C --UE -w USRP --build-eclipse diff --git a/cmake_targets/lte-simulators/CMakeLists.txt b/cmake_targets/lte-simulators/CMakeLists.txt index 0b706c8748eae45600e328daef5f39038396170d..5ed4d93d800250f7ed1eae511e6615782e5cd46e 100644 --- a/cmake_targets/lte-simulators/CMakeLists.txt +++ b/cmake_targets/lte-simulators/CMakeLists.txt @@ -8,7 +8,7 @@ set(DEBUG_PHY False) set(MU_RECIEVER False) set(RANDOM_BF False) set(PBS_SIM False) -set(PERFECT_CE False) +set(PERFECT_CE True) set(NAS_UE False) set(MESSAGE_CHART_GENERATOR False) diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt index 732ede3f94006466ae8afb9603b4f892f3d19855..81e3fe4b3ce7ac256ed4fea630ee30ec9425b2a1 100644 --- a/cmake_targets/nas_sim_tools/CMakeLists.txt +++ b/cmake_targets/nas_sim_tools/CMakeLists.txt @@ -2,70 +2,89 @@ cmake_minimum_required(VERSION 2.8) project(NAS_SIM_TOOLS) +include(FindPkgConfig) +pkg_search_module(CONFIG libconfig REQUIRED) +include_directories(${CONFIG_INCLUDE_DIRS}) +add_definitions(-std=gnu99) ENABLE_LANGUAGE(C) -#Sends the -std=c99 flag to the gcc compiler -add_definitions(-std=c99) -add_definitions(-DNAS_UE) + +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -Werror -Wall -Wstrict-prototypes -Wno-packed-bitfield-compat -g") set(OPENAIR_DIR $ENV{OPENAIR_DIR}) -set(OPENAIR1_DIR $ENV{OPENAIR_DIR}/openair1) -set(OPENAIR2_DIR $ENV{OPENAIR_DIR}/openair2) set(OPENAIR3_DIR $ENV{OPENAIR_DIR}/openair3) -set(OPENAIR3_DIR $ENV{OPENAIR_DIR}/openair3) -set(OPENAIR_TARGETS $ENV{OPENAIR_DIR}/targets) - -#set(EXECUTABLE_OUTPUT_PATH ${OPENAIR_DIR}/targets/bin) - -# Add .h files for dependancies -set(usim_SRC - ${OPENAIR_DIR}/openair3/NAS/TOOLS/usim_data.c +set(CONF2UEDATA_LIB_SRC + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_emm.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_user_data.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_usim.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_network.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_user_plmn.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_parser.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/fs.c + ${OPENAIR_DIR}/openair3/NAS/TOOLS/display.c ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/usim_api.c ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/aka_functions.c ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/memory.c ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/nas_log.c ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/OctetString.c ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/TLVEncoder.c + ${OPENAIR_DIR}/common/utils/utils.c ) -set(usim_HDR - ${OPENAIR_DIR}/openair3/NAS/TOOLS/network.h + +set(conf2uedata_HDR + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf2uedata.h + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_emm.h ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/usim_api.h ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/aka_functions.h ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/memory.h ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/nas_log.h ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/OctetString.h ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/TLVEncoder.h + ${OPENAIR_DIR}/common/utils/utils.h ) + include_directories( + ${OPENAIR_DIR}/common/utils + ${OPENAIR_DIR}/openair3/NAS/UE ${OPENAIR_DIR}/openair3/NAS/COMMON + ${OPENAIR_DIR}/openair3/NAS/UE/API/USER ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM ${OPENAIR_DIR}/openair3/NAS/UE/EMM/ ${OPENAIR_DIR}/openair3/NAS/UE/ESM/ ${OPENAIR_DIR}/openair3/NAS/COMMON/IES/ ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL ) -ADD_EXECUTABLE(usim ${usim_SRC} ${usim_HDR}) +# conf2uedata binary +set(conf2uedata_SRC + ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf2uedata.c + ${CONF2UEDATA_LIB_SRC} +) +add_executable(conf2uedata ${conf2uedata_SRC} ${conf2uedata_HDR} ) +target_link_libraries(conf2uedata ${CONFIG_LIBRARIES}) -set(nvram_SRC - ${OPENAIR_DIR}/openair3/NAS/TOOLS/ue_data.c - ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/memory.c - ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/nas_log.c -) +# usim binary -set(nvram_HDR - ${OPENAIR_DIR}/openair3/NAS/UE/EMM/emmData.h - ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/memory.h - ${OPENAIR_DIR}/openair3/NAS/COMMON/userDef.h +set(usim_SRC + ${OPENAIR_DIR}/openair3/NAS/TOOLS/usim.c + ${CONF2UEDATA_LIB_SRC} ) -ADD_EXECUTABLE(nvram ${nvram_SRC} ${nvram_HDR}) -#install (TARGETS usim DESTINATION ${EXECUTABLE_OUTPUT_PATH}) -#install (TARGETS nvram DESTINATION ${EXECUTABLE_OUTPUT_PATH}) +add_executable(usim ${usim_SRC} ${conf2uedata_HDR} ) +target_link_libraries(usim ${CONFIG_LIBRARIES}) + +# nvram binary + +set(nvram_SRC + ${OPENAIR_DIR}/openair3/NAS/TOOLS/nvram.c + ${CONF2UEDATA_LIB_SRC} +) + -#install(CODE "EXECUTE_PROCESS (COMMAND ${OPENAIR_TARGETS}/bin/nvram --gen WORKING_DIRECTORY ${OPENAIR_TARGETS}/bin)") -#install(CODE "EXECUTE_PROCESS (COMMAND ${OPENAIR_TARGETS}/bin/usim --gen WORKING_DIRECTORY ${OPENAIR_TARGETS}/bin)") +add_executable(nvram ${nvram_SRC} ${conf2uedata_HDR} ) +target_link_libraries(nvram ${CONFIG_LIBRARIES}) diff --git a/cmake_targets/snap_environment.sh b/cmake_targets/snap_environment.sh new file mode 100755 index 0000000000000000000000000000000000000000..1c0725d8b5962f63738ca2c86f0efe6188b698d3 --- /dev/null +++ b/cmake_targets/snap_environment.sh @@ -0,0 +1,3 @@ +#!/bin/sh +export UHD_IMAGES_DIR=$SNAP/uhd_images +exec $@ diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index f73078afc5e2a1be7075d520a4e5f5f0ed8685c5..a57040449c7223d191be4df7c928ed036b4e5d62 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -136,6 +136,20 @@ clean_all_files() { # Compilers ################################### +#check_warnings: +# print error message if the compilation had warnings +#argument: +# $1: log file +check_warnings() { + #we look for 'warning:' in the compilation log file + #this is how gcc starts a warning + #this is not perfect, we may get false positive + warning_count=`grep "warning:" "$1"|wc -l` + if [ $warning_count -gt 0 ]; then + echo_error "WARNING: $warning_count warnings. See $1" + fi +} + compilations() { cd $OPENAIR_DIR/cmake_targets/$1/build set +e @@ -153,6 +167,7 @@ compilations() { if [ -s $3 ] ; then cp $3 $4 echo_success "$2 compiled" + check_warnings "$dlog/$2.$REL.txt" else echo_error "$2 compilation failed" exit 1 @@ -216,7 +231,11 @@ install_usrp_uhd_driver() { # We move uhd-host apart because it depends on linux kernel version # On newer kernels, it fails to install $SUDO apt-get -y install uhd-host - $SUDO uhd_images_downloader + if [ -z $1 ]; then + $SUDO uhd_images_downloader + else + $SUDO uhd_images_downloader -i $1 + fi } check_install_bladerf_driver(){ @@ -224,7 +243,7 @@ check_install_bladerf_driver(){ $SUDO add-apt-repository -y ppa:bladerf/bladerf $SUDO apt-get update fi - $SUDO apt-get install -y--allow-unauthenticated bladerf libbladerf-dev + $SUDO apt-get install -y --allow-unauthenticated bladerf libbladerf-dev $SUDO apt-get install -y --allow-unauthenticated bladerf-firmware-fx3 $SUDO apt-get install -y --allow-unauthenticated bladerf-fpga-hostedx40 } @@ -233,6 +252,21 @@ flash_firmware_bladerf() { $SUDO bladeRF-cli --flash-firmware /usr/share/Nuand/bladeRF/bladeRF_fw.img } +check_install_lmssdr_driver(){ + if ( [ -d "/usr/local/include/lime" ] && + [ -f "/usr/local/include/lime/LimeSuite.h" ] ) + then + echo_success "Found lmssdr drivers and tools installed from source" + else + echo_error "lmssdr support implies installing lmssdr drivers and tools" \ + " from sources. check:" + echo_info "https://open-cells.com/index.php/2017/05/10/limesdr-installation/" + echo_fatal "Cannot compile lmssdr device" + fi + + +} + check_install_additional_tools (){ $SUDO apt-get update $SUDO apt-get install -y \ @@ -450,19 +484,18 @@ install_asn1c_from_source(){ ################################################ install_nas_tools() { - cd $1 - if [ ! -f .ue.nvram ]; then + if [ ! -f .ue.nvram0 ]; then echo_success "generate .ue_emm.nvram .ue.nvram" - ./nvram --gen + ./nvram --gen -c $1 -o $2 else - [ ./nvram -nt .ue.nvram -o ./nvram -nt .ue_emm.nvram ] && ./nvram --gen + [ ./nvram -nt .ue.nvram0 -o ./nvram -nt .ue_emm.nvram0 ] && ./nvram --gen -c $1 -o $2 fi - if [ ! -f .usim.nvram ]; then + if [ ! -f .usim.nvram0 ]; then echo_success "generate .usim.nvram" - ./usim --gen + ./usim --gen -c $1 -o $2 else - [ ./usim -nt .usim.nvram ] && ./usim --gen + [ ./usim -nt .usim.nvram0 ] && ./usim --gen -c $1 -o $2 fi } diff --git a/cmake_targets/tools/fix_asn1 b/cmake_targets/tools/fix_asn1 index 0661d7878de20d86741df8e222875f3e7c79ab38..805a4ce66a2a58bbc430f5ed439e3bd5217d07e8 100755 --- a/cmake_targets/tools/fix_asn1 +++ b/cmake_targets/tools/fix_asn1 @@ -3,19 +3,16 @@ # in those arrays, each line is: # <file> <sha1sum of file (without line 4 which changes depending on the location of the files)> <patch to apply to file> +RRC_Rel14=( + "SystemInformation-r8-IEs.h" 562e3c3aeb7c6d76d722f31bf24488a26e627f33 "fix_asn1.data/RRC.rel14/SystemInformation-r8-IEs.h.diff" +) + RRC_Rel10=( "SystemInformation-r8-IEs.h" 603cd6615cff36ec7020692d72c0d6de7c4859cb "fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h.diff" ) X2AP_Rel11_2=( "X2ap-CriticalityDiagnostics-IE-List.h" ae96308b37fcbcbf39da5012e42968135fc5f27b "fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h.diff" - "NativeInteger.c" 1a55f5402fd363318cf5444ffe1f67530dcf66ff "fix_asn1.data/X2AP.rel11.2/NativeInteger.c.diff" - "constr_SET_OF.c" 808cbbdf19b118c0bdb04e3acf2cbe6e4133be2b "fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c.diff" -) - -S1AP_Rel10_5=( - "NativeInteger.c" 1a55f5402fd363318cf5444ffe1f67530dcf66ff "fix_asn1.data/S1AP.rel10.5/NativeInteger.c.diff" - "constr_SET_OF.c" 808cbbdf19b118c0bdb04e3acf2cbe6e4133be2b "fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c.diff" ) red_color="$(tput setaf 1)" @@ -94,6 +91,10 @@ function patch_rrc() local version="$2" case "$version" in + Rel14 ) + echo "patching RRC files release 14" + apply_patches "$directory" RRC_Rel14 ${#RRC_Rel14[*]} + ;; Rel10 ) echo "patching RRC files release 10" apply_patches "$directory" RRC_Rel10 ${#RRC_Rel10[*]} @@ -130,8 +131,7 @@ function patch_s1ap() case "$version" in R10 ) - echo "patching S1AP files release 10.5" - apply_patches "$directory" S1AP_Rel10_5 ${#S1AP_Rel10_5[*]} + #nothing to do anymore (fixes went to asn1c) ;; * ) error unknwon/unhandled S1AP version \'"$version"\' diff --git a/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-r8-IEs.h.diff b/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-r8-IEs.h.diff new file mode 100644 index 0000000000000000000000000000000000000000..b2d32cf052ab6fb7e81887f043a8ef973ee905b8 --- /dev/null +++ b/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-r8-IEs.h.diff @@ -0,0 +1,23 @@ +73,77d72 +< /* SystemInformation-r8-IEs */ +< typedef struct SystemInformation_r8_IEs { +< struct SystemInformation_r8_IEs__sib_TypeAndInfo { +< A_SEQUENCE_OF(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member { +< SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR present; +103c98,102 +< } choice; +--- +> }; +> +> struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member { +> SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR present; +> union SystemInformation_r8_IEs__sib_TypeAndInfo__Member_u choice; +107c106,111 +< } ) list; +--- +> }; +> +> /* SystemInformation-r8-IEs */ +> typedef struct SystemInformation_r8_IEs { +> struct SystemInformation_r8_IEs__sib_TypeAndInfo { +> A_SEQUENCE_OF(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member) list; diff --git a/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/NativeInteger.c.diff b/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/NativeInteger.c.diff deleted file mode 100644 index 3b51426ad3fa008bec5131cd68d2bb0ea99d7750..0000000000000000000000000000000000000000 --- a/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/NativeInteger.c.diff +++ /dev/null @@ -1,8 +0,0 @@ -283c283 -< int dynamic = 0; ---- -> //int dynamic = 0; -290c290 -< dynamic = 1; ---- -> //dynamic = 1; diff --git a/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c.diff b/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c.diff deleted file mode 100644 index 3ceaf5e3e5ccef48746cf5abf2952aa0c6910224..0000000000000000000000000000000000000000 --- a/cmake_targets/tools/fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c.diff +++ /dev/null @@ -1,4 +0,0 @@ -1007c1007 -< (int)nelems, (int)ct ? ct->effective_bits : -1); ---- -> (int)nelems, ct ? ct->effective_bits : -1); diff --git a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/NativeInteger.c.diff b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/NativeInteger.c.diff deleted file mode 100644 index 3b51426ad3fa008bec5131cd68d2bb0ea99d7750..0000000000000000000000000000000000000000 --- a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/NativeInteger.c.diff +++ /dev/null @@ -1,8 +0,0 @@ -283c283 -< int dynamic = 0; ---- -> //int dynamic = 0; -290c290 -< dynamic = 1; ---- -> //dynamic = 1; diff --git a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c.diff b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c.diff deleted file mode 100644 index 3ceaf5e3e5ccef48746cf5abf2952aa0c6910224..0000000000000000000000000000000000000000 --- a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c.diff +++ /dev/null @@ -1,4 +0,0 @@ -1007c1007 -< (int)nelems, (int)ct ? ct->effective_bits : -1); ---- -> (int)nelems, ct ? ct->effective_bits : -1); diff --git a/cmake_targets/tools/init_nas_s1 b/cmake_targets/tools/init_nas_s1 index 5f27c5283741a122fadce4cb0c94ca0b05af58bd..003a3ae600a12cfa225b6d627af6d0c6d93a2814 100644 --- a/cmake_targets/tools/init_nas_s1 +++ b/cmake_targets/tools/init_nas_s1 @@ -33,7 +33,7 @@ # ####################################### -LTEIF=oip0 +LTEIF=oip1 #OPENAIR_DIR=/home/oai/svn-oai/openair4G load_module() { @@ -48,11 +48,11 @@ load_module() { sudo insmod $1 } -load_module $OPENAIR_DIR/targets/bin/ue_ip.ko +load_module ../../targets/bin/ue_ip.ko if [ "$1" = "UE" ]; then - echo "bring up oip0 interface for UE" - ifconfig oip0 up + echo "bring up $LTEIF interface for UE" + ifconfig $LTEIF up fi ip route flush cache diff --git a/cmake_targets/tools/run_enb_ue_virt_noS1 b/cmake_targets/tools/run_enb_ue_virt_noS1 index a0f23ecb01bc90a649d5dc6be540ea2917760f88..a5139d4b44c250ab7e1c056d45ef014988f4798b 100755 --- a/cmake_targets/tools/run_enb_ue_virt_noS1 +++ b/cmake_targets/tools/run_enb_ue_virt_noS1 @@ -150,7 +150,7 @@ function main() # -u | --num-ue ) -V | --vcd) - "setting gtk-wave output" + echo "setting gtk-wave output" exe_arguments="$exe_arguments -V /tmp/oai_gtk_wave.vcd" shift ; ;; @@ -164,6 +164,11 @@ function main() exe_arguments="$exe_arguments -n $2" shift 2; ;; + -x | --xforms) + echo "running with xforms" + exe_arguments="$exe_arguments --xforms" + shift 1; + ;; *) echo "Unknown option $1" help @@ -212,11 +217,11 @@ function main() fi if [ $run_gdb -eq 0 ]; then - exec $SUDO $OPENAIR_DIR/targets/bin/oaisim_nos1.Rel10 $exe_arguments | tee /tmp/enb_ue_nos1.log.txt + exec $SUDO $OPENAIR_DIR/targets/bin/oaisim_nos1.Rel14 $exe_arguments | tee /tmp/enb_ue_nos1.log.txt else touch ~/.gdb_enb_ue_nos1 chmod 777 ~/.gdb_enb_ue_nos1 - echo "file $OPENAIR_DIR/targets/bin/oaisim_nos1.Rel10" > ~/.gdb_enb_ue_nos1 + echo "file $OPENAIR_DIR/targets/bin/oaisim_nos1.Rel14" > ~/.gdb_enb_ue_nos1 echo "set args $exe_arguments" >> ~/.gdb_enb_ue_nos1 echo "run" >> ~/.gdb_enb_ue_nos1 cat ~/.gdb_enb_ue_nos1 diff --git a/cmake_targets/tools/run_enb_ue_virt_s1 b/cmake_targets/tools/run_enb_ue_virt_s1 index ecd5993ff47e65769d1867e72d83f875fa3ca757..8e717f393a28b637771b9698e61b7f547bb3c444 100755 --- a/cmake_targets/tools/run_enb_ue_virt_s1 +++ b/cmake_targets/tools/run_enb_ue_virt_s1 @@ -174,7 +174,7 @@ function main() ;; -V | --vcd) - "setting gtk-wave output" + echo "setting gtk-wave output" exe_arguments="$exe_arguments -V /tmp/oai_gtk_wave.vcd" shift ; ;; @@ -183,6 +183,11 @@ function main() exe_arguments="$exe_arguments -P wireshark" shift 2; ;; + -x | --xforms) + echo "running with xforms" + exe_arguments="$exe_arguments --xforms" + shift 1; + ;; *) echo "Unknown option $1" help @@ -247,12 +252,6 @@ function main() if [ $? -ne 0 ]; then echo "200 lte " >> /etc/iproute2/rt_tables fi - ip rule add fwmark 1 table lte - ifconfig oip1 up - ip route add default dev oip1 table lte - # the actual IP address depends on the EPC/MME config file for address pool - ip route add from 192.188.0.0/24 table lte - ip route add to 192.188.0.0/24 table lte exe_arguments="$exe_arguments -s15 -AAWGN -y1 -b1 -u1 -Q0" @@ -264,11 +263,11 @@ function main() fi if [ $run_gdb -eq 0 ]; then - exec $OPENAIR_DIR/targets/bin/oaisim.Rel10 $exe_arguments | tee /tmp/enb_ue_s1.log.txt + exec $OPENAIR_DIR/targets/bin/oaisim.Rel14 $exe_arguments | tee /tmp/enb_ue_s1.log.txt else touch ~/.gdb_enb_ue_s1 chmod 777 ~/.gdb_enb_ue_s1 - echo "file $OPENAIR_DIR/targets/bin/oaisim.Rel10" > ~/.gdb_enb_ue_s1 + echo "file $OPENAIR_DIR/targets/bin/oaisim.Rel14" > ~/.gdb_enb_ue_s1 echo "set args $exe_arguments" >> ~/.gdb_enb_ue_s1 echo "run" >> ~/.gdb_enb_ue_s1 cat ~/.gdb_enb_ue_s1 diff --git a/cmake_targets/tools/run_ue_s1 b/cmake_targets/tools/run_ue_s1 new file mode 100644 index 0000000000000000000000000000000000000000..56b18d72b926d983b1ee64da8b600682f647bb06 --- /dev/null +++ b/cmake_targets/tools/run_ue_s1 @@ -0,0 +1,33 @@ +#!/bin/bash + +# Carrier frequency in Hz +#FREQ=2660000000 #FDD +FREQ=2350000000 #TDD +NRB=50 +TA=0 + +#9:trace, 8/7:debug, 6:info, 4:warn, 3:error +LOGLEVEL=6 + +#enable or disable soft scope +#SCOPE='' +SCOPE='-d' + +#enable or disable VCD logging +VCD='' +#VCD='-V' + +ISTDD='-T' +#ISTDD='' + +#use external clock +ECLK="--external-clock" +#ECLK="" + +#UE scan carrier +#ISSCAN="--ue-scan-carrier" +ISSCAN="" + +sudo sh -c './init_nas_s1 UE' +cd ../../targets/bin/ +sudo -E ./lte-softmodem.Rel10 -U -C$FREQ -r$NRB $ISSCAN --ue-txgain 70 --ue-rxgain 80 -A $TA $ECLK -W $ISTDD -g $LOGLEVEL $SCOPE 2>&1 | sudo tee /tmp/UE.log diff --git a/common/utils/Makefile.inc b/common/utils/Makefile.inc deleted file mode 100644 index 33c126b8d73230a685451ff9d86136c608c1982d..0000000000000000000000000000000000000000 --- a/common/utils/Makefile.inc +++ /dev/null @@ -1,59 +0,0 @@ -export KERNEL_DIR=/lib/modules/$(shell uname -r)/ -CC=gcc -CCC=gcc -linux := $(shell if [ `uname` = "Linux" ] ; then echo "1" ; else echo "0" ; fi) - - -CFLAGS += -std=gnu99 -CFLAGS += -Wall -g -ggdb -Wstrict-prototypes -fno-strict-aliasing - -# Need to force this option because default kernel module builder is wrong -CFLAGS += $(call cc-option,-mpreferred-stack-boundary=4) - -#For performance, if some option doesn't exist in all gcc versions, use $(call cc-option,MY_OPTION) -#CFLAGS += -O2 -#CFLAGS += -funroll-loops -CFLAGS += -Wno-packed-bitfield-compat - -# This is the minimum CPU faetures for OAI -CFLAGS += -mmmx -msse -msse2 -mssse3 -msse4.1 -# Add CPU features from local CPU -#CFLAGS += -march=native - -ifeq ($(OSTYPE),Cygwin) -cygwin=1 -CFLAGS += -DCYGWIN -else -cygwin=0 -endif - -ifeq ($(linux),1) -CFLAGS += -LDFLAGS += -endif - -ITTI_DIR = $(COMMON_UTILS_DIR)/itti - -ITTI_OBJS = $(ITTI_DIR)/intertask_interface.o -ITTI_OBJS += $(ITTI_DIR)/intertask_interface_dump.o -ITTI_OBJS += $(ITTI_DIR)/backtrace.o -ITTI_OBJS += $(ITTI_DIR)/memory_pools.o -ITTI_OBJS += $(ITTI_DIR)/signals.o -ITTI_OBJS += $(ITTI_DIR)/timer.o - - -HASHTABLE_DIR = $(COMMON_UTILS_DIR)/collection/hashtable -MSC_DIR = $(COMMON_UTILS_DIR)/msc - -HASHTABLE_OBJS = $(HASHTABLE_DIR)/hashtable.o -HASHTABLE_OBJS += $(HASHTABLE_DIR)/obj_hashtable.o - -UTILS_OBJS = $(ITTI_OBJS) $(HASHTABLE_OBJS) - -UTILS_incl = \ - -I$(COMMON_UTILS_DIR) \ - -I$(HASHTABLE_DIR) \ - -I$(ITTI_DIR) \ - -I$(MSC_DIR) - -print-% : ; @echo $* = $($*) diff --git a/common/utils/T/T.h b/common/utils/T/T.h index 819615131e77cc72cf36d1f060ad61b8d1f8e2d2..37668a830973dc668530ec685acabd0cf3ea1de5 100644 --- a/common/utils/T/T.h +++ b/common/utils/T/T.h @@ -184,8 +184,30 @@ extern T_cache_t *T_cache; } while (0) #endif +/* we have 4 versions of T_HEADER: + * - bad quality C++ version with time + * - good quality C version with time + * - bad quality C++ version without time + * - good quality C version without time + */ + #ifdef T_SEND_TIME +#ifdef __cplusplus + +/* C++ version of T_HEADER with time */ +#define T_HEADER(x) \ + do { \ + struct timespec T_HEADER_time; \ + if (clock_gettime(CLOCK_REALTIME, &T_HEADER_time)) abort(); \ + memcpy(T_LOCAL_buf, &T_HEADER_time, sizeof(struct timespec)); \ + T_LOCAL_size += sizeof(struct timespec); \ + T_PUT_int(1, (int)(uintptr_t)(x)); \ + } while (0) + +#else /* #ifdef __cplusplus */ + +/* C version of T_HEADER with time */ #define T_HEADER(x) \ do { \ if (!__builtin_types_compatible_p(typeof(x), struct T_header *)) { \ @@ -201,8 +223,21 @@ extern T_cache_t *T_cache; T_PUT_int(1, (int)(uintptr_t)(x)); \ } while (0) +#endif /* #ifdef __cplusplus */ + #else /* #ifdef T_SEND_TIME */ +#ifdef __cplusplus + +/* C++ version of T_HEADER without time */ +#define T_HEADER(x) \ + do { \ + T_PUT_int(1, (int)(uintptr_t)(x)); \ + } while (0) + +#else /* #ifdef __cplusplus */ + +/* C version of T_HEADER without time */ #define T_HEADER(x) \ do { \ if (!__builtin_types_compatible_p(typeof(x), struct T_header *)) { \ @@ -214,6 +249,8 @@ extern T_cache_t *T_cache; T_PUT_int(1, (int)(uintptr_t)(x)); \ } while (0) +#endif /* #ifdef __cplusplus */ + #endif /* #ifdef T_SEND_TIME */ #define T1(t) \ diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 09ed098ee0fb591bc2fa1b878601d9eec14ca6de..c78bc92d364c183fac608cf71ad462a251644749 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -28,7 +28,7 @@ ID = ENB_PHY_DLSCH_UE_NACK ID = ENB_PHY_ULSCH_UE_DCI DESC = eNodeB uplink UE specific DCI as sent by the PHY layer GROUP = ALL:PHY:GRAPHIC:ENB - FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS + FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS : int,L : int,firstCCE ID = ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION DESC = eNodeB uplink UE retransmission due to PHICH NACK (see generate_phich_top) GROUP = ALL:PHY:GRAPHIC:ENB diff --git a/common/utils/itti/assertions.h b/common/utils/itti/assertions.h index df8251d10541cfd06a402172c8aa4087e5fd40b6..a411bd539728b93cb563ad39843f5eefbf5bd88e 100644 --- a/common/utils/itti/assertions.h +++ b/common/utils/itti/assertions.h @@ -65,7 +65,7 @@ _Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX " (intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3) #define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \ -_Assert_(cOND, _Assert_Exit_, #vALUE1": %"PRIdMAX"\n"#vALUE2": %"PRIdMAX"\n"#vALUE3": %"PRIdMAX"\n"#vALUE4": %"PRIdMAX"\n\n", \ +_Assert_(cOND, _Assert_Exit_, #vALUE1": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n" #vALUE4 ": %" PRIdMAX "\n\n", \ (intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4) #define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3) diff --git a/common/utils/itti/memory_pools.c b/common/utils/itti/memory_pools.c index b317cfd2fa50ba9542c98346133681481d68bc01..955e29440ac24f96dcf37dc24c3b981a985762ca 100644 --- a/common/utils/itti/memory_pools.c +++ b/common/utils/itti/memory_pools.c @@ -77,7 +77,7 @@ typedef struct items_group_s { } items_group_t; /*------------------------------------------------------------------------------*/ -static const items_group_position_t ITEMS_GROUP_POSITION_INVALID = -1; +//static const items_group_position_t ITEMS_GROUP_POSITION_INVALID = -1; static const items_group_index_t ITEMS_GROUP_INDEX_INVALID = -1; /*------------------------------------------------------------------------------*/ diff --git a/common/utils/system.c b/common/utils/system.c new file mode 100644 index 0000000000000000000000000000000000000000..52fb950e37f2179c9c4de895c1ab9dd456f93230 --- /dev/null +++ b/common/utils/system.c @@ -0,0 +1,186 @@ +/* + * 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.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.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 + */ + +/* This module provides a separate process to run system(). + * The communication between this process and the main processing + * is done through unix pipes. + * + * Motivation: the UE sets its IP address using system() and + * that disrupts realtime processing in some cases. Having a + * separate process solves this problem. + */ + +#include "system.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> + +#define MAX_COMMAND 4096 + +static int command_pipe_read; +static int command_pipe_write; +static int result_pipe_read; +static int result_pipe_write; + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +static int module_initialized = 0; + +/********************************************************************/ +/* util functions */ +/********************************************************************/ + +static void lock_system(void) +{ + if (pthread_mutex_lock(&lock) != 0) { + printf("pthread_mutex_lock fails\n"); + abort(); + } +} + +static void unlock_system(void) +{ + if (pthread_mutex_unlock(&lock) != 0) { + printf("pthread_mutex_unlock fails\n"); + abort(); + } +} + +static void write_pipe(int p, char *b, int size) +{ + while (size) { + int ret = write(p, b, size); + if (ret <= 0) exit(0); + b += ret; + size -= ret; + } +} + +static void read_pipe(int p, char *b, int size) +{ + while (size) { + int ret = read(p, b, size); + if (ret <= 0) exit(0); + b += ret; + size -= ret; + } +} + +/********************************************************************/ +/* background process */ +/********************************************************************/ + +/* This function is run by background process. It waits for a command, + * runs it, and reports status back. It exits (in normal situations) + * when the main process exits, because then a "read" on the pipe + * will return 0, in which case "read_pipe" exits. + */ +static void background_system_process(void) +{ + int len; + int ret; + char command[MAX_COMMAND+1]; + + while (1) { + read_pipe(command_pipe_read, (char*)&len, sizeof(int)); + read_pipe(command_pipe_read, command, len); + ret = system(command); + write_pipe(result_pipe_write, (char *)&ret, sizeof(int)); + } +} + +/********************************************************************/ +/* background_system() */ +/* return -1 on error, 0 on success */ +/********************************************************************/ + +int background_system(char *command) +{ + int res; + int len; + + if (module_initialized == 0) { + printf("FATAL: calling 'background_system' but 'start_background_system' was not called\n"); + abort(); + } + + len = strlen(command)+1; + if (len > MAX_COMMAND) { + printf("FATAL: command too long. Increase MAX_COMMAND (%d).\n", MAX_COMMAND); + printf("command was: '%s'\n", command); + abort(); + } + /* only one command can run at a time, so let's lock/unlock */ + lock_system(); + write_pipe(command_pipe_write, (char*)&len, sizeof(int)); + write_pipe(command_pipe_write, command, len); + read_pipe(result_pipe_read, (char*)&res, sizeof(int)); + unlock_system(); + if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) return -1; + return 0; +} + +/********************************************************************/ +/* start_background_system() */ +/* initializes the "background system" module */ +/* to be called very early by the main processing */ +/********************************************************************/ + +void start_background_system(void) +{ + int p[2]; + pid_t son; + + module_initialized = 1; + + if (pipe(p) == -1) { + perror("pipe"); + exit(1); + } + command_pipe_read = p[0]; + command_pipe_write = p[1]; + + if (pipe(p) == -1) { + perror("pipe"); + exit(1); + } + result_pipe_read = p[0]; + result_pipe_write = p[1]; + + son = fork(); + if (son == -1) { + perror("fork"); + exit(1); + } + + if (son) { + close(result_pipe_write); + close(command_pipe_read); + return; + } + + close(result_pipe_read); + close(command_pipe_write); + + background_system_process(); +} diff --git a/common/utils/system.h b/common/utils/system.h new file mode 100644 index 0000000000000000000000000000000000000000..784c15fc9a045d6b83e5136fe00122a65c7789b6 --- /dev/null +++ b/common/utils/system.h @@ -0,0 +1,39 @@ +/* + * 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.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.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 + */ + +#ifndef _SYSTEM_H_OAI_ +#define _SYSTEM_H_OAI_ + +/**************************************************** + * send a command to the background process + * return -1 on error, 0 on success + ****************************************************/ + +int background_system(char *command); + +/**************************************************** + * initialize the background process + * to be called very early + ****************************************************/ + +void start_background_system(void); + +#endif /* _SYSTEM_H_OAI_ */ diff --git a/common/utils/time_utils.h b/common/utils/time_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..ee82c8cf95366cddec208bbc213d2dfcfbcf2ec6 --- /dev/null +++ b/common/utils/time_utils.h @@ -0,0 +1,23 @@ +#ifndef _TIME_UTILS_H_ +#define _TIME_UTILS_H_ + +#include <time.h> +#include <stdint.h> + +static inline int64_t clock_difftime_ns(struct timespec start, struct timespec end) +{ + struct timespec temp; + int64_t temp_ns; + + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + temp_ns = (int64_t)(temp.tv_sec) * (int64_t)1000000000 + (temp.tv_nsec); + return temp_ns; +} + +#endif /* _TIME_UTILS_H_ */ diff --git a/common/utils/utils.c b/common/utils/utils.c new file mode 100644 index 0000000000000000000000000000000000000000..a807a27096f661002d87ab5023291aa62b34fe89 --- /dev/null +++ b/common/utils/utils.c @@ -0,0 +1,107 @@ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include "utils.h" + +void *calloc_or_fail(size_t size) { + void *ptr = calloc(1, size); + if (ptr == NULL) { + fprintf(stderr, "[UE] Failed to calloc %zu bytes", size); + exit(EXIT_FAILURE); + } + return ptr; +} + +void *malloc_or_fail(size_t size) { + void *ptr = malloc(size); + if (ptr == NULL) { + fprintf(stderr, "[UE] Failed to malloc %zu bytes", size); + exit(EXIT_FAILURE); + } + return ptr; +} + +/**************************************************************************** + ** ** + ** Name: hex_char_to_hex_value() ** + ** ** + ** Description: Converts an hexadecimal ASCII coded digit into its value. ** + ** ** + ** Inputs: c: A char holding the ASCII coded value ** + ** Others: None ** + ** ** + ** Outputs: None ** + ** Return: Converted value (-1 on error) ** + ** Others: None ** + ** ** + ***************************************************************************/ +int hex_char_to_hex_value (char c) +{ + if (!((c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F') || + (c >= '0' && c <= '9'))) + return -1; + + if (c >= 'A') { + /* Remove case bit */ + c &= ~('a' ^ 'A'); + + return (c - 'A' + 10); + } else { + return (c - '0'); + } +} + +/**************************************************************************** + ** ** + ** Name: hex_string_to_hex_value() ** + ** ** + ** Description: Converts an hexadecimal ASCII coded string into its value.** + ** ** + ** Inputs: hex_value: A pointer to the location to store the ** + ** conversion result ** + ** size: The size of hex_value in bytes ** + ** Others: None ** + ** ** + ** Outputs: hex_value: Converted value ** + ** Return: 0 on success, -1 on error ** + ** Others: None ** + ** ** + ***************************************************************************/ +int hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size) +{ + int i; + + if (strlen(hex_string) != size*2) { + fprintf(stderr, "the string '%s' should be of length %d\n", hex_string, size*2); + return -1; + } + + for (i=0; i < size; i++) { + int a = hex_char_to_hex_value(hex_string[2 * i]); + int b = hex_char_to_hex_value(hex_string[2 * i + 1]); + if (a == -1 || b == -1) goto error; + hex_value[i] = (a << 4) | b; + } + return 0; + +error: + fprintf(stderr, "the string '%s' is not a valid hexadecimal string\n", hex_string); + for (i=0; i < size; i++) + hex_value[i] = 0; + return -1; +} + +char *itoa(int i) { + char buffer[64]; + int ret; + + ret = snprintf(buffer, sizeof(buffer), "%d",i); + if ( ret <= 0 ) { + return NULL; + } + + return strdup(buffer); +} + diff --git a/common/utils/utils.h b/common/utils/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..cfe3df34b9356e02fe33e050198af154b415a472 --- /dev/null +++ b/common/utils/utils.h @@ -0,0 +1,17 @@ +#ifndef _UTILS_H +#define _UTILS_H + +#include <stdint.h> +#include <sys/types.h> + +void *calloc_or_fail(size_t size); +void *malloc_or_fail(size_t size); + +// Converts an hexadecimal ASCII coded digit into its value. ** +int hex_char_to_hex_value (char c); +// Converts an hexadecimal ASCII coded string into its value.** +int hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size); + +char *itoa(int i); + +#endif diff --git a/openair1/PHY/INIT/README.txt b/openair1/PHY/INIT/README.txt index d40d0feecd1a816f4f7a9a5fd04577680520618d..520e0acd4fa2d6fc23130677a6c874e70a7491c6 100644 --- a/openair1/PHY/INIT/README.txt +++ b/openair1/PHY/INIT/README.txt @@ -2,4 +2,6 @@ This directory contains files related to initialization of variables/structures init_top.c : initialize top-level variables and signal buffers, FFT twiddle factors, etc. lte_init.c : LTE specific initlization routines (DLSCH/ULSCH signal buffers for RX, data buffers for TX, etc.) -init.c : non-LTE initialization routines (to be removed) +lte_param_init.c: used only in unitary simulations. initializes the global variables eNB and UE. +lte_parms.c: contains init_frame_parms to initialize frame parameters structure + diff --git a/openair1/PHY/INIT/defs.h b/openair1/PHY/INIT/defs.h index 27303cb57dc91deb0e58968e1d23197ab03de19a..61cc063fb3da2fafb5d8701caa7f0dcfaf29b61f 100644 --- a/openair1/PHY/INIT/defs.h +++ b/openair1/PHY/INIT/defs.h @@ -31,7 +31,7 @@ #include "TDD-Config.h" #include "MBSFN-SubframeConfigList.h" #include "MobilityControlInfo.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "SCellToAddMod-r10.h" #endif /** @addtogroup _PHY_STRUCTURES_ @@ -317,7 +317,7 @@ void lte_param_init(unsigned char N_tx_port_eNB, uint8_t osf, uint32_t perfect_ce); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) void phy_config_dedicated_scell_ue(uint8_t Mod_id, uint8_t eNB_index, SCellToAddMod_r10_t *sCellToAddMod_r10, diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index f6f8d8f858cfc5e9c8a46927a0555b47456081c2..53c12d04cf7ab6f71826bba3fecec49446609aee 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -483,7 +483,8 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB) if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) { if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) { - + + eNB->soundingrs_ul_config_dedicated[UE_id].srsConfigDedicatedSetup = 1; eNB->soundingrs_ul_config_dedicated[UE_id].duration = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration; eNB->soundingrs_ul_config_dedicated[UE_id].cyclicShift = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift; eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition; @@ -614,8 +615,12 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility // RNTI - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); + + LOG_I(PHY,"SET C-RNTI %x %x\n",PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti, + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti); } if(ho_failed) { @@ -665,34 +670,34 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, if (physicalConfigDedicated->antennaInfo) { switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) { case AntennaInfoDedicated__transmissionMode_tm1: - eNB->transmission_mode[UE_id] = 1; - break; + eNB->transmission_mode[UE_id] = 1; + break; case AntennaInfoDedicated__transmissionMode_tm2: - eNB->transmission_mode[UE_id] = 2; - break; + eNB->transmission_mode[UE_id] = 2; + break; case AntennaInfoDedicated__transmissionMode_tm3: - eNB->transmission_mode[UE_id] = 3; - break; + eNB->transmission_mode[UE_id] = 3; + break; case AntennaInfoDedicated__transmissionMode_tm4: - eNB->transmission_mode[UE_id] = 4; - break; + eNB->transmission_mode[UE_id] = 4; + break; case AntennaInfoDedicated__transmissionMode_tm5: - eNB->transmission_mode[UE_id] = 5; - break; + eNB->transmission_mode[UE_id] = 5; + break; case AntennaInfoDedicated__transmissionMode_tm6: - eNB->transmission_mode[UE_id] = 6; - break; + eNB->transmission_mode[UE_id] = 6; + break; case AntennaInfoDedicated__transmissionMode_tm7: lte_gold_ue_spec_port5(eNB->lte_gold_uespec_port5_table[0],eNB->frame_parms.Nid_cell,rnti); - eNB->do_precoding = 1; - eNB->transmission_mode[UE_id] = 7; - break; + eNB->do_precoding = 1; + eNB->transmission_mode[UE_id] = 7; + break; default: - LOG_E(PHY,"Unknown transmission mode!\n"); - break; + LOG_E(PHY,"Unknown transmission mode!\n"); + break; } LOG_I(PHY,"Transmission Mode (phy_config_dedicated_eNB) %d\n",eNB->transmission_mode[UE_id]); - + } else { LOG_D(PHY,"[eNB %d] : Received NULL radioResourceConfigDedicated->antennaInfo from eNB %d\n",Mod_id,UE_id); } @@ -702,7 +707,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) void phy_config_dedicated_scell_ue(uint8_t Mod_id, uint8_t eNB_index, SCellToAddMod_r10_t *sCellToAddMod_r10, @@ -835,34 +840,34 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id, if (physicalConfigDedicated->antennaInfo) { phy_vars_ue->transmission_mode[eNB_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode); - LOG_D(PHY,"Transmission Mode %d\n",phy_vars_ue->transmission_mode[eNB_id]); + LOG_I(PHY,"Transmission Mode %d\n",phy_vars_ue->transmission_mode[eNB_id]); switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) { case AntennaInfoDedicated__transmissionMode_tm1: - phy_vars_ue->transmission_mode[eNB_id] = 1; - break; + phy_vars_ue->transmission_mode[eNB_id] = 1; + break; case AntennaInfoDedicated__transmissionMode_tm2: - phy_vars_ue->transmission_mode[eNB_id] = 2; - break; + phy_vars_ue->transmission_mode[eNB_id] = 2; + break; case AntennaInfoDedicated__transmissionMode_tm3: - phy_vars_ue->transmission_mode[eNB_id] = 3; - break; + phy_vars_ue->transmission_mode[eNB_id] = 3; + break; case AntennaInfoDedicated__transmissionMode_tm4: - phy_vars_ue->transmission_mode[eNB_id] = 4; - break; + phy_vars_ue->transmission_mode[eNB_id] = 4; + break; case AntennaInfoDedicated__transmissionMode_tm5: - phy_vars_ue->transmission_mode[eNB_id] = 5; - break; + phy_vars_ue->transmission_mode[eNB_id] = 5; + break; case AntennaInfoDedicated__transmissionMode_tm6: - phy_vars_ue->transmission_mode[eNB_id] = 6; - break; + phy_vars_ue->transmission_mode[eNB_id] = 6; + break; case AntennaInfoDedicated__transmissionMode_tm7: - lte_gold_ue_spec_port5(phy_vars_ue->lte_gold_uespec_port5_table, phy_vars_ue->frame_parms.Nid_cell, phy_vars_ue->pdcch_vars[eNB_id]->crnti); - phy_vars_ue->transmission_mode[eNB_id] = 7; - break; + lte_gold_ue_spec_port5(phy_vars_ue->lte_gold_uespec_port5_table, phy_vars_ue->frame_parms.Nid_cell, phy_vars_ue->pdcch_vars[0][eNB_id]->crnti); + phy_vars_ue->transmission_mode[eNB_id] = 7; + break; default: - LOG_E(PHY,"Unknown transmission mode!\n"); - break; - } + LOG_E(PHY,"Unknown transmission mode!\n"); + break; + } } else { LOG_D(PHY,"[UE %d] Received NULL physicalConfigDedicated->antennaInfo from eNB %d\n",Mod_id, eNB_id); } @@ -906,29 +911,29 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id, if (physicalConfigDedicated->cqi_ReportConfig) { if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) { - // configure PUSCH CQI reporting - phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; - if ((phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm12) && - (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm30) && - (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm31)) - LOG_E(PHY,"Unsupported Aperiodic CQI Feedback Mode : %d\n",phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic); + // configure PUSCH CQI reporting + phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; + if ((phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm12) && + (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm30) && + (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm31)) + LOG_E(PHY,"Unsupported Aperiodic CQI Feedback Mode : %d\n",phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic); } if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) { - if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_setup) { - // configure PUCCH CQI reporting - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex; - if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex) - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex; - } - else if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_release) { - // handle release - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1; - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1; - } + if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_setup) { + // configure PUCCH CQI reporting + phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; + phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex; + if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex) + phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex; + } + else if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_release) { + // handle release + phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1; + phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1; + } } } - + #ifdef CBA if (physicalConfigDedicated->pusch_CBAConfigDedicated_vlola) { @@ -948,6 +953,19 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id, // fill cqi parameters for periodic CQI reporting get_cqipmiri_params(phy_vars_ue,eNB_id); + // disable MIB SIB decoding once we are on connected mode + LOG_I(PHY,"Disabling SIB MIB decoding \n"); + phy_vars_ue->decode_SIB = 0; + phy_vars_ue->decode_MIB = 0; + //phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti; + if(phy_vars_ue->pdcch_vars[0][eNB_id]->crnti == 0x1234) + phy_vars_ue->pdcch_vars[0][eNB_id]->crnti = phy_vars_ue->pdcch_vars[1][eNB_id]->crnti; + else + phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti; + + LOG_I(PHY,"C-RNTI %x %x \n", phy_vars_ue->pdcch_vars[0][eNB_id]->crnti, + phy_vars_ue->pdcch_vars[1][eNB_id]->crnti); + } void phy_config_cba_rnti (module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, rnti_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups) @@ -1016,8 +1034,9 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS pdsch->pmi_ext = (uint8_t*)malloc16_clear( fp->N_RB_DL ); pdsch->llr[0] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); pdsch->llr128 = (int16_t**)malloc16_clear( sizeof(int16_t*) ); - pdsch->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) ); // FIXME! no further allocation for (int16_t*)pdsch->llr128 !!! expect SIGSEGV + // FK, 11-3-2015: this is only as a temporary pointer, no memory is stored there + pdsch->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->rxdataF_uespec_pilots = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); @@ -1026,11 +1045,12 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS pdsch->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_bf_ch_estimates = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_bf_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + //pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + //pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_ch_mag0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_ch_magb0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + // the allocated memory size is fixed: AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" ); @@ -1046,15 +1066,14 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS pdsch->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_bf_ch_estimates[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2); pdsch->dl_bf_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdsch->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + //pdsch->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + //pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_mag0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_magb0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); } } } - int phy_init_lte_ue(PHY_VARS_UE *ue, int nb_connected_eNB, uint8_t abstraction_flag) @@ -1069,10 +1088,11 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, LTE_UE_PDSCH** const pdsch_vars_ra = ue->pdsch_vars_ra; LTE_UE_PDSCH** const pdsch_vars_mch = ue->pdsch_vars_MCH; LTE_UE_PBCH** const pbch_vars = ue->pbch_vars; - LTE_UE_PDCCH** const pdcch_vars = ue->pdcch_vars; + LTE_UE_PDCCH** const pdcch_vars_th0 = ue->pdcch_vars[0]; + LTE_UE_PDCCH** const pdcch_vars_th1 = ue->pdcch_vars[1]; LTE_UE_PRACH** const prach_vars = ue->prach_vars; - int i,j,k; + int i,j,k,l; int eNB_id; printf("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,fp->nb_antennas_tx,fp->nb_antennas_rx); @@ -1151,7 +1171,8 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); pdsch_vars_mch[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); - pdcch_vars[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH)); + pdcch_vars_th0[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH)); + pdcch_vars_th1[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH)); prach_vars[eNB_id] = (LTE_UE_PRACH *)malloc16_clear(sizeof(LTE_UE_PRACH)); pbch_vars[eNB_id] = (LTE_UE_PBCH *)malloc16_clear(sizeof(LTE_UE_PBCH)); @@ -1160,68 +1181,113 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, phy_init_lte_ue__PDSCH( pdsch_vars_th1[eNB_id], fp ); // thread 0 - pdsch_vars_th0[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12); - pdsch_vars_th0[eNB_id]->llr_shifts_p = pdsch_vars_th0[eNB_id]->llr_shifts; - pdsch_vars_th0[eNB_id]->dl_ch_mag1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch_vars_th0[eNB_id]->dl_ch_magb1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch_vars_th0[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + pdsch_vars_th0[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12); + pdsch_vars_th0[eNB_id]->llr_shifts_p = pdsch_vars_th0[eNB_id]->llr_shifts; + pdsch_vars_th0[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + pdsch_vars_th0[eNB_id]->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) ); + pdsch_vars_th0[eNB_id]->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) ); + + // thread 0 + pdsch_vars_th1[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12); + pdsch_vars_th1[eNB_id]->llr_shifts_p = pdsch_vars_th0[eNB_id]->llr_shifts; + pdsch_vars_th1[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + pdsch_vars_th1[eNB_id]->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) ); + pdsch_vars_th1[eNB_id]->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) ); + + - for (k=0; k<8; k++) - pdsch_vars_th0[eNB_id]->rxdataF_comp1[k] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - // thread 1 - pdsch_vars_th1[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12); - pdsch_vars_th1[eNB_id]->llr_shifts_p = pdsch_vars_th1[eNB_id]->llr_shifts; - pdsch_vars_th1[eNB_id]->dl_ch_mag1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch_vars_th1[eNB_id]->dl_ch_magb1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch_vars_th1[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + for (int i=0; i<fp->nb_antennas_rx; i++){ + pdsch_vars_th0[eNB_id]->rho[i] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th1[eNB_id]->rho[i] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + } - for (k=0; k<8; k++) - pdsch_vars_th1[eNB_id]->rxdataF_comp1[k] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th0[eNB_id]->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th1[eNB_id]->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); for (i=0; i<fp->nb_antennas_rx; i++) for (j=0; j<4; j++) { - int idx = (j<<1)+i; - pdsch_vars_th0[eNB_id]->dl_ch_mag1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - pdsch_vars_th0[eNB_id]->dl_ch_magb1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + const int idx = (j<<1)+i; + const size_t num = 7*2*fp->N_RB_DL*12+4; + pdsch_vars_th0[eNB_id]->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdsch_vars_th1[eNB_id]->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + } - pdsch_vars_th1[eNB_id]->dl_ch_mag1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - pdsch_vars_th1[eNB_id]->dl_ch_magb1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - for (k=0; k<8; k++) - { - pdsch_vars_th0[eNB_id]->rxdataF_comp1[idx][k] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*14) ); - pdsch_vars_th1[eNB_id]->rxdataF_comp1[idx][k] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*14) ); - } + //const size_t num = 7*2*fp->N_RB_DL*12+4; + for (k=0;k<8;k++) { //harq_pid + for (l=0;l<8;l++) { //round + pdsch_vars_th0[eNB_id]->rxdataF_comp1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th0[eNB_id]->dl_ch_rho_ext[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th0[eNB_id]->dl_ch_mag1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th0[eNB_id]->dl_ch_magb1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + + pdsch_vars_th1[eNB_id]->rxdataF_comp1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th1[eNB_id]->dl_ch_rho_ext[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th1[eNB_id]->dl_ch_mag1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars_th1[eNB_id]->dl_ch_magb1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + + + for (int i=0; i<fp->nb_antennas_rx; i++) + for (int j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++) + const int idx = (j<<1)+i; + pdsch_vars_th0[eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th0[eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th0[eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th0[eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + + pdsch_vars_th1[eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th1[eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th1[eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars_th1[eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + } } - + } phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], fp ); phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], fp ); phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp ); - // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE - pdcch_vars[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - pdcch_vars[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - pdcch_vars[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - pdcch_vars[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 ); - pdcch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdcch_vars[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdcch_vars[eNB_id]->rho = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pdcch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdcch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE + pdcch_vars_th0[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars_th0[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars_th0[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars_th0[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 ); + + pdcch_vars_th0[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars_th0[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars_th0[eNB_id]->rho = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pdcch_vars_th0[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars_th0[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + + pdcch_vars_th1[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars_th1[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars_th1[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars_th1[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 ); + + pdcch_vars_th1[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars_th1[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars_th1[eNB_id]->rho = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pdcch_vars_th1[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars_th1[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); for (i=0; i<fp->nb_antennas_rx; i++) { //ue_pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*7*2) ); - pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) ); + pdcch_vars_th0[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) ); + pdcch_vars_th1[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) ); for (j=0; j<4; j++) { //fp->nb_antennas_tx; j++) int idx = (j<<1)+i; // size_t num = 7*2*fp->N_RB_DL*12; size_t num = 4*100*12; // 4 symbols, 100 PRBs, 12 REs per PRB - pdcch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdcch_vars[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdcch_vars[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdcch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th0[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th0[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th0[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th0[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + + pdcch_vars_th1[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th1[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th1[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars_th1[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); } } @@ -1267,12 +1333,20 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, ue->sinr_CQI_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); ue->init_averaging = 1; - ue->pdsch_config_dedicated->p_a = dB0; // default value until overwritten by RRCConnectionReconfiguration + // default value until overwritten by RRCConnectionReconfiguration + if (fp->nb_antenna_ports_eNB==2) + ue->pdsch_config_dedicated->p_a = dBm3; + else + ue->pdsch_config_dedicated->p_a = dB0; // set channel estimation to do linear interpolation in time ue->high_speed_flag = 1; ue->ch_est_alpha = 24576; + // enable MIB/SIB decoding by default + ue->decode_MIB = 1; + ue->decode_SIB = 1; + init_prach_tables(839); @@ -1290,9 +1364,11 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, LTE_eNB_PUSCH** const pusch_vars = eNB->pusch_vars; LTE_eNB_SRS* const srs_vars = eNB->srs_vars; LTE_eNB_PRACH* const prach_vars = &eNB->prach_vars; - int i, j, eNB_id, UE_id; + + int i, j, eNB_id, UE_id; int re; + eNB->total_dlsch_bitrate = 0; eNB->total_transmitted_bits = 0; eNB->total_system_throughput = 0; @@ -1307,17 +1383,17 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, lte_gold(fp,eNB->lte_gold_table,fp->Nid_cell); generate_pcfich_reg_mapping(fp); generate_phich_reg_mapping(fp); - + for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { eNB->first_run_timing_advance[UE_id] = - 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. + 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. // clear whole structure bzero( &eNB->UE_stats[UE_id], sizeof(LTE_eNB_UE_stats) ); - + eNB->physicalConfigDedicated[UE_id] = NULL; } - + eNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. } @@ -1325,131 +1401,142 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, { eNB_id=0; if (abstraction_flag==0) { - + // TX vars if (eNB->node_function != NGFI_RCC_IF4p5) - common_vars->txdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_tx*sizeof(int32_t*)); + + common_vars->txdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_tx*sizeof(int32_t*)); common_vars->txdataF[eNB_id] = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*)); common_vars->txdataF_BF[eNB_id] = (int32_t **)malloc16(fp->nb_antennas_tx*sizeof(int32_t*)); if (eNB->node_function != NGFI_RRU_IF5) { - for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) { - if (i<fp->nb_antenna_ports_eNB || i==5) { - common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); + for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) { + if (i<fp->nb_antenna_ports_eNB || i==5) { + common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); #ifdef DEBUG_PHY - printf("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%lu bytes)\n", - eNB_id,i,common_vars->txdataF[eNB_id][i], - fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t)); + printf("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%lu bytes)\n", + eNB_id,i,common_vars->txdataF[eNB_id][i], + fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t)); #endif - } - } + } + } } + for (i=0; i<fp->nb_antennas_tx; i++) { - common_vars->txdataF_BF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t) ); - if (eNB->node_function != NGFI_RCC_IF4p5) + common_vars->txdataF_BF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t) ); + if (eNB->node_function != NGFI_RCC_IF4p5) - // Allocate 10 subframes of I/Q TX signal data (time) if not - common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); + // Allocate 10 subframes of I/Q TX signal data (time) if not + common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); #ifdef DEBUG_PHY - printf("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->txdata[eNB_id][i], - fp->samples_per_tti*10*sizeof(int32_t)); + printf("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->txdata[eNB_id][i], + fp->samples_per_tti*10*sizeof(int32_t)); #endif } - + for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) { - if (i<fp->nb_antenna_ports_eNB || i==5) { - common_vars->beam_weights[eNB_id][i] = (int32_t **)malloc16_clear(fp->nb_antennas_tx*sizeof(int32_t*)); - for (j=0; j<fp->nb_antennas_tx; j++) { - common_vars->beam_weights[eNB_id][i][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t)); - // antenna ports 0-3 are mapped on antennas 0-3 - // antenna port 4 is mapped on antenna 0 - // antenna ports 5-14 are mapped on all antennas - if (((i<4) && (i==j)) || ((i==4) && (j==0))) { - for (re=0; re<fp->ofdm_symbol_size; re++) - common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff; - } - else if (i>4) { - for (re=0; re<fp->ofdm_symbol_size; re++) - common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff/fp->nb_antennas_tx; - } + if (i<fp->nb_antenna_ports_eNB || i==5) { + common_vars->beam_weights[eNB_id][i] = (int32_t **)malloc16_clear(fp->nb_antennas_tx*sizeof(int32_t*)); + for (j=0; j<fp->nb_antennas_tx; j++) { + common_vars->beam_weights[eNB_id][i][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t)); + // antenna ports 0-3 are mapped on antennas 0-3 + // antenna port 4 is mapped on antenna 0 + // antenna ports 5-14 are mapped on all antennas + if (((i<4) && (i==j)) || ((i==4) && (j==0))) { + for (re=0; re<fp->ofdm_symbol_size; re++) + common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff; + } + else if (i>4) { + for (re=0; re<fp->ofdm_symbol_size; re++) + common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff/fp->nb_antennas_tx; + } #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] lte_common_vars->beam_weights[%d][%d][%d] = %p (%d bytes)\n", - eNB_id,i,j,common_vars->beam_weights[eNB_id][i][j], - fp->ofdm_symbol_size*sizeof(int32_t)); + msg("[openair][LTE_PHY][INIT] lte_common_vars->beam_weights[%d][%d][%d] = %p (%zu bytes)\n", + eNB_id,i,j,common_vars->beam_weights[eNB_id][i][j], + fp->ofdm_symbol_size*sizeof(int32_t)); #endif - } - } + } + } } + // RX vars if (eNB->node_function != NGFI_RCC_IF4p5) { - common_vars->rxdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) ); - common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) ); } + common_vars->rxdataF[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) ); + for (i=0; i<fp->nb_antennas_rx; i++) { - if (eNB->node_function != NGFI_RCC_IF4p5) { - // allocate 2 subframes of I/Q signal data (time) if not an RCC (no time-domain signals) - common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); - - if (eNB->node_function != NGFI_RRU_IF5) - // allocate 2 subframes of I/Q signal data (time, 7.5 kHz offset) - common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( 2*fp->samples_per_tti*2*sizeof(int32_t) ); - } - if (eNB->node_function != NGFI_RRU_IF5) - // allocate 2 subframes of I/Q signal data (frequency) - common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(2*fp->ofdm_symbol_size*fp->symbols_per_tti) ); + if (eNB->node_function != NGFI_RCC_IF4p5) { + // allocate 2 subframes of I/Q signal data (time) if not an RCC (no time-domain signals) + common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); + + if (eNB->node_function != NGFI_RRU_IF5) + // allocate 2 subframes of I/Q signal data (time, 7.5 kHz offset) + common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( 2*fp->samples_per_tti*2*sizeof(int32_t) ); + } + + if (eNB->node_function != NGFI_RRU_IF5) + // allocate 2 subframes of I/Q signal data (frequency) + common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(2*fp->ofdm_symbol_size*fp->symbols_per_tti) ); + #ifdef DEBUG_PHY - printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata[eNB_id][i],fp->samples_per_tti*10*sizeof(int32_t)); - if (eNB->node_function != NGFI_RRU_IF5) - printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i],fp->samples_per_tti*2*sizeof(int32_t)); + printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata[eNB_id][i],fp->samples_per_tti*10*sizeof(int32_t)); + if (eNB->node_function != NGFI_RRU_IF5) + printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i],fp->samples_per_tti*2*sizeof(int32_t)); #endif common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti) ); } - + + if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) { - // Channel estimates for SRS - for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - - srs_vars[UE_id].srs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; i<fp->nb_antennas_rx; i++) { - srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); - srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); - } - } //UE_id - - common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_tti ); + + // Channel estimates for SRS + for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { + + srs_vars[UE_id].srs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + + for (i=0; i<fp->nb_antennas_rx; i++) { + srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); + srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); + } + } //UE_id + + common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_tti ); } } // abstraction_flag = 0 else { //UPLINK abstraction = 1 eNB->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); } } //eNB_id - - - + + + if (abstraction_flag==0) { if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) { generate_ul_ref_sigs_rx(); - + // SRS for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - srs_vars[UE_id].srs = (int32_t*)malloc16_clear(2*fp->ofdm_symbol_size*sizeof(int32_t)); + srs_vars[UE_id].srs = (int32_t*)malloc16_clear(2*fp->ofdm_symbol_size*sizeof(int32_t)); } } } - - - + + + // ULSCH VARS, skip if NFGI_RRU_IF4 - + + if ((eNB->node_function!=NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) + prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); - + /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ AssertFatal(fp->nb_antennas_rx <= sizeof(prach_vars->rxsigF) / sizeof(prach_vars->rxsigF[0]), "nb_antennas_rx too large"); @@ -1459,10 +1546,11 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, printf("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); #endif } - + if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) { + AssertFatal(fp->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]), - "nb_antennas_rx too large"); + "nb_antennas_rx too large"); for (i=0; i<fp->nb_antennas_rx; i++) { prach_vars->prach_ifft[i] = (int16_t*)malloc16_clear(1024*2*sizeof(int16_t)); #ifdef DEBUG_PHY @@ -1471,77 +1559,81 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, } for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - + //FIXME pusch_vars[UE_id] = (LTE_eNB_PUSCH*)malloc16_clear( NUMBER_OF_UE_MAX*sizeof(LTE_eNB_PUSCH) ); - + if (abstraction_flag==0) { - for (eNB_id=0; eNB_id<3; eNB_id++) { - - pusch_vars[UE_id]->rxdataF_ext[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; i<fp->nb_antennas_rx; i++) { - // RK 2 times because of output format of FFT! - // FIXME We should get rid of this - pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*fp->ofdm_symbol_size ); - pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - } - } //eNB_id - - pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + for (eNB_id=0; eNB_id<3; eNB_id++) { + + pusch_vars[UE_id]->rxdataF_ext[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + + for (i=0; i<fp->nb_antennas_rx; i++) { + // RK 2 times because of output format of FFT! + // FIXME We should get rid of this + pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*fp->ofdm_symbol_size ); + pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + } + } //eNB_id + + pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); } // abstraction_flag } //UE_id - + if (abstraction_flag==0) { if (is_secondary_eNB) { - for (eNB_id=0; eNB_id<3; eNB_id++) { - eNB->dl_precoder_SeNB[eNB_id] = (int **)malloc16(4*sizeof(int*)); - - if (eNB->dl_precoder_SeNB[eNB_id]) { + for (eNB_id=0; eNB_id<3; eNB_id++) { + eNB->dl_precoder_SeNB[eNB_id] = (int **)malloc16(4*sizeof(int*)); + + if (eNB->dl_precoder_SeNB[eNB_id]) { #ifdef DEBUG_PHY - printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id, - eNB->dl_precoder_SeNB[eNB_id]); + printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id, + eNB->dl_precoder_SeNB[eNB_id]); #endif - } else { - printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id); - return(-1); - } - - for (j=0; j<fp->nb_antennas_tx; j++) { - eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(fp->ofdm_symbol_size)); // repeated format (hence the '2*') - - if (eNB->dl_precoder_SeNB[eNB_id][j]) { + } else { + printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id); + return(-1); + } + + for (j=0; j<fp->nb_antennas_tx; j++) { + eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(fp->ofdm_symbol_size)); // repeated format (hence the '2*') + + if (eNB->dl_precoder_SeNB[eNB_id][j]) { #ifdef DEBUG_PHY - printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, - eNB->dl_precoder_SeNB[eNB_id][j]); + printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, + eNB->dl_precoder_SeNB[eNB_id][j]); #endif - memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(fp->ofdm_symbol_size)); - } else { - printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); - return(-1); - } - } //for(j=...nb_antennas_tx - - } //for(eNB_id... + memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(fp->ofdm_symbol_size)); + } else { + printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); + return(-1); + } + } //for(j=...nb_antennas_tx + + } //for(eNB_id... } } - + for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) eNB->UE_stats_ptr[UE_id] = &eNB->UE_stats[UE_id]; - - eNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration + + //defaul value until overwritten by RRCConnectionReconfiguration + if (fp->nb_antenna_ports_eNB==2) + eNB->pdsch_config_dedicated->p_a = dBm3; + else + eNB->pdsch_config_dedicated->p_a = dB0; init_prach_tables(839); } // node_function != NGFI_RRU_IF4p5 diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index 4625eba4303eb959494dc28cf34e59eebe42dcf4..f3833b770914737e8b325a2e27bdb9e413a48e3c 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -121,9 +121,9 @@ void lte_param_init(unsigned char N_tx_port_eNB, UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB ((UE->frame_parms).pdsch_config_common).p_b = 0; } else { // rho_a = rhob - eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + eNB->pdsch_config_dedicated->p_a = dBm3; // 4 = 0dB ((eNB->frame_parms).pdsch_config_common).p_b = 1; - UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + UE->pdsch_config_dedicated->p_a = dBm3; // 4 = 0dB ((UE->frame_parms).pdsch_config_common).p_b = 1; } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c index df6a55eaf35560a90f619b01e824e145cea2e212..7e112342ce15980c0e199cc930c6428ea8347db7 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c @@ -1,31 +1,24 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom +/* + * 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.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.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 + */ - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see <http://www.gnu.org/licenses/>. - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ #ifdef USER_MODE #include <string.h> #endif @@ -58,10 +51,10 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, int uespec_pilot[300]; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; - LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch[eNB_id]; + LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch[(Ns>>1)&0x1][eNB_id]; LTE_DL_UE_HARQ_t *dlsch0_harq; - harq_pid = dlsch_ue[0]->current_harq_pid; + harq_pid = dlsch_ue[0]->current_harq_pid; dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) || diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c index b34331eb8d4614d3a13b83c9583b722d89b0d649..9743c68a22a2071e84fef4ed29c36293c8441429 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c @@ -23,6 +23,7 @@ #include <string.h> #endif #include "defs.h" +#include "SCHED/defs.h" #include "PHY/defs.h" #include "filt96_32.h" #include "T.h" @@ -637,105 +638,129 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue, 32767-ue->ch_est_alpha, dl_ch-(ue->frame_parms.ofdm_symbol_size<<1),0,ue->frame_parms.ofdm_symbol_size); } else { // high_speed_flag == 1 - if (symbol == 0) { - // printf("Interpolating %d->0\n",4-ue->frame_parms.Ncp); - // dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][(4-ue->frame_parms.Ncp)*(ue->frame_parms.ofdm_symbol_size)]; + if ((symbol == 0)) { + // printf("Interpolating %d->0\n",4-ue->frame_parms.Ncp); + // dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][(4-ue->frame_parms.Ncp)*(ue->frame_parms.ofdm_symbol_size)]; if(((Ns>>1)!=0) || ( ((Ns>>1)==0) && interpolateS11S12)) { - //LOG_D(PHY,"Interpolate s11-->s0 to get s12 and s13 Ns %d \n", Ns); - dl_ch_prev = (int16_t *)&dl_ch_estimates_previous[(p<<1)+aarx][pilot3*(ue->frame_parms.ofdm_symbol_size)]; + //LOG_I(PHY,"Interpolate s11-->s0 to get s12 and s13 Ns %d \n", Ns); + dl_ch_prev = (int16_t *)&dl_ch_estimates_previous[(p<<1)+aarx][pilot3*(ue->frame_parms.ofdm_symbol_size)]; + + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); + } + + interpolateS11S12 = 1; + } // this is 1/3,2/3 combination for pilots spaced by 3 symbols + else if (symbol == pilot1) { + dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][0]; + + //LOG_I(PHY,"Interpolate s0-->s4 to get s1 s2 and s3 Ns %d \n", Ns); + if (ue->frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) + + uint8_t previous_subframe; + if(Ns>>1 == 0) + previous_subframe = 9; + else + previous_subframe = ((Ns>>1) - 1 )%9; + + if((subframe_select(&ue->frame_parms,previous_subframe) == SF_UL)) + { + + multadd_complex_vector_real_scalar(dl_ch_prev,328,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,32440,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,328,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,32440,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,32440,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + } + else + { + multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + + } + } else { + multadd_complex_vector_real_scalar(dl_ch_prev,328,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)<<1),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); + } // pilot spacing 3 symbols (1/3,2/3 combination) + } else if (symbol == pilot2) { + dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot1*(ue->frame_parms.ofdm_symbol_size)]; multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - } - - interpolateS11S12 = 1; - } // this is 1/3,2/3 combination for pilots spaced by 3 symbols - else if (symbol == pilot1) { - dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][0]; - - if (ue->frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) - multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - } else { - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)<<1),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - } // pilot spacing 3 symbols (1/3,2/3 combination) - } else if (symbol == pilot2) { - dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot1*(ue->frame_parms.ofdm_symbol_size)]; - - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - } else { // symbol == pilot3 - // printf("Interpolating 0->%d\n",4-ue->frame_parms.Ncp); - dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(ue->frame_parms.ofdm_symbol_size)]; - - if (ue->frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) - multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - } else { - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)<<1),1,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - } // pilot spacing 3 symbols (1/3,2/3 combination) - - if((ue->rx_offset_diff !=0) && ((Ns>>1) == 9)) - { - //LOG_D(PHY,"Extrapolate s7-->s11 to get s12 and s13 Ns %d\n", Ns); - interpolateS11S12 = 0; - //LOG_E(PHY,"Interpolate s7--s11 s12 s13 pilot 3 Ns %d l %d symbol %d \n", Ns, l, symbol); - int16_t *dlChEst_ofdm11 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot3*(ue->frame_parms.ofdm_symbol_size)]; - int16_t *dlChEst_ofdm7 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(ue->frame_parms.ofdm_symbol_size)]; - - // interpolate ofdm s12: 5/4*ofdms11 + -1/4*ofdms7 5/4 q1.15 40960 -1/4 q1.15 8192 - int16_t *dlChEst_ofdm12 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][12*ue->frame_parms.ofdm_symbol_size]; - for(int i=0; i<(2*ue->frame_parms.ofdm_symbol_size); i++) - { - int64_t tmp_mult = 0; - tmp_mult = ((int64_t)dlChEst_ofdm11[i] * 40960 - (int64_t)dlChEst_ofdm7[i] * 8192); + } else { // symbol == pilot3 + // printf("Interpolating 0->%d\n",4-ue->frame_parms.Ncp); + dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(ue->frame_parms.ofdm_symbol_size)]; - tmp_mult = tmp_mult >> 15; - dlChEst_ofdm12[i] = tmp_mult; - } + if (ue->frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) + multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - // interpolate ofdm s13: 3/2*ofdms11 + -1/2*ofdms7 3/2 q1.15 49152 1/2 q1.15 16384 - int16_t *dlChEst_ofdm13 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][13*ue->frame_parms.ofdm_symbol_size]; - for(int i=0; i<(2*ue->frame_parms.ofdm_symbol_size); i++) - { - int64_t tmp_mult = 0; - tmp_mult = ((int64_t)dlChEst_ofdm11[i] * 49152 - (int64_t)dlChEst_ofdm7[i] * 16384); + multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + } else { + multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); + + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)<<1),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); + } // pilot spacing 3 symbols (1/3,2/3 combination) - tmp_mult = tmp_mult >> 15; - dlChEst_ofdm13[i] = tmp_mult; + if((ue->rx_offset_diff !=0) && ((Ns>>1) == 9)) + { + //LOG_I(PHY,"Extrapolate s7-->s11 to get s12 and s13 Ns %d\n", Ns); + interpolateS11S12 = 0; + //LOG_E(PHY,"Interpolate s7--s11 s12 s13 pilot 3 Ns %d l %d symbol %d \n", Ns, l, symbol); + int16_t *dlChEst_ofdm11 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot3*(ue->frame_parms.ofdm_symbol_size)]; + int16_t *dlChEst_ofdm7 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(ue->frame_parms.ofdm_symbol_size)]; + + // interpolate ofdm s12: 5/4*ofdms11 + -1/4*ofdms7 5/4 q1.15 40960 -1/4 q1.15 8192 + int16_t *dlChEst_ofdm12 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][12*ue->frame_parms.ofdm_symbol_size]; + for(int i=0; i<(2*ue->frame_parms.ofdm_symbol_size); i++) + { + int64_t tmp_mult = 0; + tmp_mult = ((int64_t)dlChEst_ofdm11[i] * 40960 - (int64_t)dlChEst_ofdm7[i] * 8192); + + tmp_mult = tmp_mult >> 15; + dlChEst_ofdm12[i] = tmp_mult; + } + + // interpolate ofdm s13: 3/2*ofdms11 + -1/2*ofdms7 3/2 q1.15 49152 1/2 q1.15 16384 + int16_t *dlChEst_ofdm13 = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][13*ue->frame_parms.ofdm_symbol_size]; + for(int i=0; i<(2*ue->frame_parms.ofdm_symbol_size); i++) + { + int64_t tmp_mult = 0; + tmp_mult = ((int64_t)dlChEst_ofdm11[i] * 49152 - (int64_t)dlChEst_ofdm7[i] * 16384); + + tmp_mult = tmp_mult >> 15; + dlChEst_ofdm13[i] = tmp_mult; + } } - } + } } - } } } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c index e6551033f31fc1891dda98b0401cc1da959b63b4..6ce10723c67909058352cb4ec2b8756068de8174 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -581,10 +581,10 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain *peak_val_out = peak_val; if (peak_val <= (40*(uint32_t)mean_val)) { - LOG_D(PHY,"[SYNC TIME] No peak found (%u,%u,%u,%u)\n",peak_pos,peak_val,mean_val,40*mean_val); + LOG_D(PHY,"[SYNC TIME] No peak found (%u,%u,%"PRIu64",%"PRIu64")\n",peak_pos,peak_val,mean_val,40*mean_val); return(-1); } else { - LOG_D(PHY,"[SYNC TIME] Peak found at pos %u, val = %u, mean_val = %u\n",peak_pos,peak_val,mean_val); + LOG_D(PHY,"[SYNC TIME] Peak found at pos %u, val = %u, mean_val = %"PRIu64"\n",peak_pos,peak_val,mean_val); return(peak_pos); } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c index db8fe548a295382ddebbd2a143236183ae7077b7..4033e4c37835351927db640fe5f11cc1ea0b0a01 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c @@ -171,20 +171,25 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, { uint8_t subframe = slot>>1; - int aarx,rb,n; + int aarx,rb; + uint8_t pss_symb; + uint8_t sss_symb; + + int32_t **rxdataF; int16_t *rxF,*rxF_pss,*rxF_sss; uint16_t Nid_cell = ue->frame_parms.Nid_cell; uint8_t eNB_offset,nu,l,nushift,k; uint16_t off; - uint8_t isPss; // indicate if this is a slot for extracting PSS - uint8_t isSss; // indicate if this is a slot for extracting SSS - int32_t pss_ext[4][72]; // contain the extracted 6*12 REs for mapping the PSS - int32_t sss_ext[4][72]; // contain the extracted 6*12 REs for mapping the SSS - int32_t (*xss_ext)[72]; // point to either pss_ext or sss_ext for common calculation - int16_t *re,*im; // real and imag part of each 32-bit xss_ext[][] value + //uint8_t isPss; // indicate if this is a slot for extracting PSS + //uint8_t isSss; // indicate if this is a slot for extracting SSS + //int32_t pss_ext[4][72]; // contain the extracted 6*12 REs for mapping the PSS + //int32_t sss_ext[4][72]; // contain the extracted 6*12 REs for mapping the SSS + //int32_t (*xss_ext)[72]; // point to either pss_ext or sss_ext for common calculation + //int16_t *re,*im; // real and imag part of each 32-bit xss_ext[][] value + //LOG_I(PHY,"UE RRC MEAS Start Subframe %d Frame Type %d slot %d \n",subframe,ue->frame_parms.frame_type,slot); for (eNB_offset = 0; eNB_offset<1+ue->measurements.n_adj_cells; eNB_offset++) { if (eNB_offset==0) { @@ -192,27 +197,28 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, //ue->measurements.n0_power_tot = 0; if (abstraction_flag == 0) { - if ((ue->frame_parms.frame_type == FDD) && - ((subframe == 0) || (subframe == 5))) { // FDD PSS/SSS, compute noise in DTX REs + if ( ((ue->frame_parms.frame_type == FDD) && ((subframe == 0) || (subframe == 5))) || + ((ue->frame_parms.frame_type == TDD) && ((subframe == 1) || (subframe == 6))) + ) + { // FDD PSS/SSS, compute noise in DTX REs if (ue->frame_parms.Ncp==NORMAL) { for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) { + + if(ue->frame_parms.frame_type == FDD) + { rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(5*ue->frame_parms.ofdm_symbol_size)]; rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)]; - - + } + else + { + rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF[aarx][(13*ue->frame_parms.ofdm_symbol_size)]; + rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(2*ue->frame_parms.ofdm_symbol_size)]; + } //-ve spectrum from SSS - // printf("slot %d: SSS DTX: %d,%d, non-DTX %d,%d\n",slot,rxF_pss[-72],rxF_pss[-71],rxF_pss[-36],rxF_pss[-35]); - // ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); - // printf("sssn36 %d\n",ue->measurements.n0_power[aarx]); - ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); - ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); - ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); - // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); - // printf("sssm32 %d\n",ue->measurements.n0_power[aarx]); //+ve spectrum from SSS - ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); @@ -223,18 +229,34 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+66]*rxF_pss[2+66])+((int32_t)rxF_pss[2+65]*rxF_pss[2+65])); // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+64]*rxF_pss[2+64])+((int32_t)rxF_pss[2+63]*rxF_pss[2+63])); // printf("pss32 %d\n",ue->measurements.n0_power[aarx]); //-ve spectrum from PSS - rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)]; + if(ue->frame_parms.frame_type == FDD) + { + rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)]; + rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)]; + } + else + { + rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF[aarx][(14*ue->frame_parms.ofdm_symbol_size)]; + rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(3*ue->frame_parms.ofdm_symbol_size)]; + } // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); // printf("pssm36 %d\n",ue->measurements.n0_power[aarx]); ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); + + ue->measurements.n0_power[aarx] = (((int32_t)rxF_sss[-70]*rxF_sss[-70])+((int32_t)rxF_sss[-69]*rxF_sss[-69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[-68]*rxF_sss[-68])+((int32_t)rxF_sss[-67]*rxF_sss[-67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[-66]*rxF_sss[-66])+((int32_t)rxF_sss[-65]*rxF_sss[-65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); // printf("pssm32 %d\n",ue->measurements.n0_power[aarx]); ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/12); ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx]; } + //LOG_I(PHY,"Subframe %d RRC UE MEAS Noise Level %d \n", subframe, ue->measurements.n0_power_tot); + ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(12*aarx)); ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size); } else { @@ -242,86 +264,61 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, } } else if ((ue->frame_parms.frame_type == TDD) && - ((slot == 2) || (slot == 12) || (slot == 1) || (slot == 11))) { // TDD PSS/SSS, compute noise in DTX REs // 2016-09-29 wilson fix incorrect noise power calculation - -#if 1 // fixing REs extraction in noise power calculation + ((subframe == 1) || (subframe == 6))) { // TDD PSS/SSS, compute noise in DTX REs // 2016-09-29 wilson fix incorrect noise power calculation - // check if this slot has a PSS or SSS sequence - if ((slot == 2) || (slot == 12)) { - isPss = 1; - } else { - isPss = 0; - } - if ((slot == 1) || (slot == 11)) { - isSss = 1; - } else { - isSss = 0; - } - if (isPss) { - pss_only_extract(ue, pss_ext); - xss_ext = pss_ext; - } - - if (isSss) { - sss_only_extract(ue, sss_ext); - xss_ext = sss_ext; - } - - // calculate noise power - int num_tot=0; // number of REs totally used in calculating noise power - for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) { - - int num_per_rx=0; // number of REs used in caluclaing noise power for this RX antenna - ue->measurements.n0_power[aarx] = 0; - for (n=2; n<70; n++) { // skip the 2 REs next to PDSCH, i.e. n={0,1,70,71} - if (n==5) {n=67;} - - re = (int16_t*)(&(xss_ext[aarx][n])); - im = re+1; - ue->measurements.n0_power[aarx] += (*re)*(*re) + (*im)*(*im); - num_per_rx++; - num_tot++; - } - - ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/(num_per_rx)); - ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx]; - } - - ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(num_tot)); - ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size); - -#else + pss_symb = 2; + sss_symb = ue->frame_parms.symbols_per_tti-1; if (ue->frame_parms.Ncp==NORMAL) { for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) { - rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)]; - // note this is a dummy pointer, the pss is not really there! - // in FDD the pss is in the symbol after the sss, but not in TDD - rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)]; - - //-ve spectrum from SSS - // ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); - ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); - ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); - ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); - // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); - //+ve spectrum from SSS - // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+72]*rxF_sss[2+72])+((int32_t)rxF_sss[2+71]*rxF_sss[2+71])); - ue->measurements.n0_power[aarx] = (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); - ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); - ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); - // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); - - ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/(6)); - ue->measurements.n0_power_tot += ue->measurements.n0_power[aarx]; - } - ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(6*aarx)); - ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size); - - + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe&0x1)].rxdataF; + rxF_pss = (int16_t *) &rxdataF[aarx][((pss_symb*(ue->frame_parms.ofdm_symbol_size)))]; + + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF; + rxF_sss = (int16_t *) &rxdataF[aarx][((sss_symb*(ue->frame_parms.ofdm_symbol_size)))]; + + //-ve spectrum from SSS + // printf("slot %d: SSS DTX: %d,%d, non-DTX %d,%d\n",slot,rxF_pss[-72],rxF_pss[-71],rxF_pss[-36],rxF_pss[-35]); + + // ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); + // printf("sssn36 %d\n",ue->measurements.n0_power[aarx]); + ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); + // printf("sssm32 %d\n",ue->measurements.n0_power[aarx]); + //+ve spectrum from SSS + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); + // printf("sssp32 %d\n",ue->measurements.n0_power[aarx]); + //+ve spectrum from PSS + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+70]*rxF_pss[2+70])+((int32_t)rxF_pss[2+69]*rxF_pss[2+69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+68]*rxF_pss[2+68])+((int32_t)rxF_pss[2+67]*rxF_pss[2+67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+66]*rxF_pss[2+66])+((int32_t)rxF_pss[2+65]*rxF_pss[2+65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+64]*rxF_pss[2+64])+((int32_t)rxF_pss[2+63]*rxF_pss[2+63])); + // printf("pss32 %d\n",ue->measurements.n0_power[aarx]); //-ve spectrum from PSS + rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)]; + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); + // printf("pssm36 %d\n",ue->measurements.n0_power[aarx]); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); + // printf("pssm32 %d\n",ue->measurements.n0_power[aarx]); + ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/12); + ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx]; + } + + ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(12*aarx)); + ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size); + + + //LOG_I(PHY,"Subframe %d RRC UE MEAS Noise Level %d \n", subframe, ue->measurements.n0_power_tot); + } -#endif } } } @@ -363,7 +360,7 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, // if ((ue->frame_rx&0x3ff) == 0) // printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1]))); - + off+=12; if (off>=(ue->frame_parms.ofdm_symbol_size<<1)) @@ -474,6 +471,14 @@ void lte_ue_measurements(PHY_VARS_UE *ue, LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; int nb_subbands,subband_size,last_subband_size; int N_RB_DL = frame_parms->N_RB_DL; + ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; + + if (ue->transmission_mode[eNB_id]!=4) + ue->measurements.rank[eNB_id] = 0; + else + ue->measurements.rank[eNB_id] = 1; + // printf ("tx mode %d\n", ue->transmission_mode[eNB_id]); + // printf ("rank %d\n", ue->PHY_measurements.rank[eNB_id]); switch (N_RB_DL) { case 6: @@ -541,6 +546,8 @@ void lte_ue_measurements(PHY_VARS_UE *ue, (((k1*((long long int)(ue->measurements.rx_power_avg[eNB_id]))) + (k2*((long long int)(ue->measurements.rx_power_tot[eNB_id]))))>>10); + //LOG_I(PHY,"Noise Power Computation: k1 %d k2 %d n0 avg %d n0 tot %d\n", k1, k2, ue->measurements.n0_power_avg, + // ue->measurements.n0_power_tot); ue->measurements.n0_power_avg = (int) (((k1*((long long int) (ue->measurements.n0_power_avg))) + (k2*((long long int) (ue->measurements.n0_power_tot))))>>10); @@ -558,8 +565,9 @@ void lte_ue_measurements(PHY_VARS_UE *ue, ue->measurements.wideband_cqi_avg[eNB_id] = dB_fixed2(ue->measurements.rx_power_avg[eNB_id],ue->measurements.n0_power_avg); ue->measurements.rx_rssi_dBm[eNB_id] = ue->measurements.rx_power_avg_dB[eNB_id] - ue->rx_total_gain_dB; #ifdef DEBUG_MEAS_UE - LOG_D(PHY,"[eNB %d] RSSI %d dBm, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n", + LOG_I(PHY,"[eNB %d] Subframe %d, RSSI %d dBm, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n", eNB_id, + subframe, ue->measurements.rx_rssi_dBm[eNB_id], ue->measurements.rx_power_avg_dB[eNB_id], ue->measurements.wideband_cqi_avg[eNB_id], @@ -625,6 +633,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue, } for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + //printf("aarx=%d", aarx); // skip the first 4 RE due to interpolation filter length of 5 (not possible to skip 5 due to 128i alignment, must be multiple of 128bit) #if defined(__x86_64__) || defined(__i386__) @@ -644,9 +653,11 @@ void lte_ue_measurements(PHY_VARS_UE *ue, // pmi #if defined(__x86_64__) || defined(__i386__) - pmi128_re = _mm_setzero_si128(); - pmi128_im = _mm_setzero_si128(); + + pmi128_re = _mm_xor_si128(pmi128_re,pmi128_re); + pmi128_im = _mm_xor_si128(pmi128_im,pmi128_im); #elif defined(__arm__) + pmi128_re = vdupq_n_s32(0); pmi128_im = vdupq_n_s32(0); #endif @@ -659,18 +670,52 @@ void lte_ue_measurements(PHY_VARS_UE *ue, for (i=0; i<limit; i++) { +#if defined(__x86_64__) || defined(__i386__) + mmtmpPMI0 = _mm_xor_si128(mmtmpPMI0,mmtmpPMI0); + mmtmpPMI1 = _mm_xor_si128(mmtmpPMI1,mmtmpPMI1); + // For each RE in subband perform ch0 * conj(ch1) // multiply by conjugated channel -#if defined(__x86_64__) || defined(__i386__) - mmtmpPMI1 = _mm_shufflelo_epi16(dl_ch1_128[0],_MM_SHUFFLE(2,3,0,1));//_MM_SHUFFLE(2,3,0,1) + // print_ints("ch0",&dl_ch0_128[0]); + // print_ints("ch1",&dl_ch1_128[0]); + + mmtmpPMI0 = _mm_madd_epi16(dl_ch0_128[0],dl_ch1_128[0]); + // print_ints("re",&mmtmpPMI0); + mmtmpPMI1 = _mm_shufflelo_epi16(dl_ch1_128[0],_MM_SHUFFLE(2,3,0,1)); + // print_ints("_mm_shufflelo_epi16",&mmtmpPMI1); mmtmpPMI1 = _mm_shufflehi_epi16(mmtmpPMI1,_MM_SHUFFLE(2,3,0,1)); + // print_ints("_mm_shufflehi_epi16",&mmtmpPMI1); mmtmpPMI1 = _mm_sign_epi16(mmtmpPMI1,*(__m128i*)&conjugate[0]); + // print_ints("_mm_sign_epi16",&mmtmpPMI1); mmtmpPMI1 = _mm_madd_epi16(mmtmpPMI1,dl_ch0_128[0]); + // print_ints("mm_madd_epi16",&mmtmpPMI1); // mmtmpPMI1 contains imag part of 4 consecutive outputs (32-bit) + pmi128_re = _mm_add_epi32(pmi128_re,mmtmpPMI0); + // print_ints(" pmi128_re 0",&pmi128_re); + pmi128_im = _mm_add_epi32(pmi128_im,mmtmpPMI1); + // print_ints(" pmi128_im 0 ",&pmi128_im); + + /* mmtmpPMI0 = _mm_xor_si128(mmtmpPMI0,mmtmpPMI0); + mmtmpPMI1 = _mm_xor_si128(mmtmpPMI1,mmtmpPMI1); + mmtmpPMI0 = _mm_madd_epi16(dl_ch0_128[1],dl_ch1_128[1]); + // print_ints("re",&mmtmpPMI0); + mmtmpPMI1 = _mm_shufflelo_epi16(dl_ch1_128[1],_MM_SHUFFLE(2,3,0,1)); + // print_ints("_mm_shufflelo_epi16",&mmtmpPMI1); + mmtmpPMI1 = _mm_shufflehi_epi16(mmtmpPMI1,_MM_SHUFFLE(2,3,0,1)); + // print_ints("_mm_shufflehi_epi16",&mmtmpPMI1); + mmtmpPMI1 = _mm_sign_epi16(mmtmpPMI1,*(__m128i*)&conjugate); + // print_ints("_mm_sign_epi16",&mmtmpPMI1); + mmtmpPMI1 = _mm_madd_epi16(mmtmpPMI1,dl_ch0_128[1]); + // print_ints("mm_madd_epi16",&mmtmpPMI1); + // mmtmpPMI1 contains imag part of 4 consecutive outputs (32-bit) pmi128_re = _mm_add_epi32(pmi128_re,mmtmpPMI0); + // print_ints(" pmi128_re 1",&pmi128_re); pmi128_im = _mm_add_epi32(pmi128_im,mmtmpPMI1); + //print_ints(" pmi128_im 1 ",&pmi128_im);*/ + #elif defined(__arm__) + mmtmpPMI0 = vmull_s16(((int16x4_t*)dl_ch0_128)[0], ((int16x4_t*)dl_ch1_128)[0]); mmtmpPMI1 = vmull_s16(((int16x4_t*)dl_ch0_128)[1], ((int16x4_t*)dl_ch1_128)[1]); pmi128_re = vqaddq_s32(pmi128_re,vcombine_s32(vpadd_s32(vget_low_s32(mmtmpPMI0),vget_high_s32(mmtmpPMI0)),vpadd_s32(vget_low_s32(mmtmpPMI1),vget_high_s32(mmtmpPMI1)))); @@ -730,7 +775,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue, } } - ue->measurements.rank[eNB_id] = 0; + //ue->measurements.rank[eNB_id] = 0; for (i=0; i<nb_subbands; i++) { ue->measurements.selected_rx_antennas[eNB_id][i] = 0; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 4fef74dd1cc2bb1a714b42081793001fd008f9cd..22ed10ebb7c2f3874c7a82f3af786f523361dd00 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -667,28 +667,28 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, } extern uint16_t transmission_offset_tdd[16]; -#define DEBUG_SRS +//#define DEBUG_SRS int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, LTE_eNB_COMMON *common_vars, LTE_eNB_SRS *srs_vars, SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, - unsigned char sub_frame_number, + unsigned char subframe, unsigned char eNB_id) { - int T_SFC,aa; + int aa; int N_symb,symbol; - uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB; + uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; #ifdef DEBUG_SRS char fname[40], vname[40]; #endif - uint8_t Ssrs = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig; + //uint8_t Ssrs = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig; + //uint8_t T_SFC = (Ssrs<=7 ? 5 : 10); N_symb = 2*7-frame_parms->Ncp; - symbol = (sub_frame_number+1)*N_symb-1; //SRS is always in last symbol of subframe - T_SFC = (Ssrs<=7 ? 5 : 10); + symbol = N_symb-1; //SRS is always in last symbol of subframe /* msg("SRS channel estimation eNB %d, subframs %d, %d %d %d %d %d\n",eNB_id,sub_frame_number, @@ -699,19 +699,21 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, SRS_parms->Ssrs); */ - if ((1<<(sub_frame_number%T_SFC))&transmission_offset_tdd[Ssrs]) { + //if ((1<<(sub_frame_number%T_SFC))&transmission_offset_tdd[Ssrs]) { - if (generate_srs_rx(frame_parms, - soundingrs_ul_config_dedicated, - srs_vars->srs)==-1) { - msg("lte_srs_channel_estimation: Error in generate_srs_rx\n"); + if (generate_srs(frame_parms, + soundingrs_ul_config_dedicated, + &srs_vars->srs[eNB_id], + 0x7FFF, + subframe)==-1) { + LOG_E(PHY,"lte_srs_channel_estimation: Error in generate_srs_rx\n"); return(-1); } for (aa=0; aa<nb_antennas_rx; aa++) { #ifdef DEBUG_SRS msg("SRS channel estimation eNB %d, subframs %d, aarx %d, %p, %p, %p\n",eNB_id,sub_frame_number,aa, - &common_vars->rxdataF[eNB_id][aa][2*frame_parms->ofdm_symbol_size*symbol], + &common_vars->rxdataF[eNB_id][aa][frame_parms->ofdm_symbol_size*symbol], srs_vars->srs, srs_vars->srs_ch_estimates[eNB_id][aa]); #endif @@ -719,14 +721,15 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, //write_output("eNB_rxF.m","rxF",&common_vars->rxdataF[0][aa][2*frame_parms->ofdm_symbol_size*symbol],2*(frame_parms->ofdm_symbol_size),2,1); //write_output("eNB_srs.m","srs_eNB",common_vars->srs,(frame_parms->ofdm_symbol_size),1,1); - mult_cpx_conj_vector((int16_t*) &common_vars->rxdataF[eNB_id][aa][2*frame_parms->ofdm_symbol_size*symbol], - (int16_t*) srs_vars->srs, + //memcpy(srs_vars->srs_ch_estimates[eNB_id][aa],&srs_vars->srs[eNB_id],frame_parms->ofdm_symbol_size*sizeof(int32_t)); + //memcpy(srs_vars->srs_ch_estimates[eNB_id][aa],&common_vars->rxdataF[eNB_id][aa][frame_parms->ofdm_symbol_size*symbol],frame_parms->ofdm_symbol_size*sizeof(int32_t)); + mult_cpx_conj_vector((int16_t*) &common_vars->rxdataF[eNB_id][aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*) &srs_vars->srs[eNB_id], (int16_t*) srs_vars->srs_ch_estimates[eNB_id][aa], frame_parms->ofdm_symbol_size, 15, 0); - //msg("SRS channel estimation cmult out\n"); #ifdef USER_MODE #ifdef DEBUG_SRS sprintf(fname,"eNB_id%d_an%d_srs_ch_est.m",eNB_id,aa); @@ -735,7 +738,6 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, #endif #endif } - } /* else { diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c old mode 100644 new mode 100755 index 49fe90bf15c0f58668d8e12f010aa4b46a2fe842..8b7a81829795a21d92ffe99587f072f174d3ba01 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -1682,9 +1682,7 @@ void pdcch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, int32_t avgP[4]; -int32_t rx_pdcch(LTE_UE_COMMON *common_vars, - LTE_UE_PDCCH **pdcch_vars, - LTE_DL_FRAME_PARMS *frame_parms, +int32_t rx_pdcch(PHY_VARS_UE *ue, uint32_t frame, uint8_t subframe, uint8_t eNB_id, @@ -1693,6 +1691,10 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars, uint8_t is_secondary_ue) { + LTE_UE_COMMON *common_vars = &ue->common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars[subframe & 0x1]; + uint8_t log2_maxh,aatx,aarx; #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 @@ -1701,7 +1703,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars, uint8_t n_pdcch_symbols = 3; //pdcch_vars[eNB_id]->num_pdcch_symbols; uint8_t mi = get_mi(frame_parms,subframe); - // printf("In rx_pdcch, subframe %d, eNB_id %d\n",subframe,eNB_id); + //printf("In rx_pdcch, subframe %d, eNB_id %d, pdcch_vars %d \n",subframe,eNB_id,pdcch_vars); for (s=0; s<n_pdcch_symbols; s++) { if (is_secondary_ue == 1) { @@ -1876,12 +1878,12 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars, pdcch_vars[eNB_id], mimo_mode); + if (n_pdcch_symbols>3) n_pdcch_symbols=1; #ifdef DEBUG_DCI_DECODING - printf("[PDCCH] subframe %d n_pdcch_symbols from PCFICH =%d\n",subframe,n_pdcch_symbols); printf("demapping: subframe %d, mi %d, tdd_config %d\n",subframe,get_mi(frame_parms,subframe),frame_parms->tdd_config); #endif @@ -1977,6 +1979,9 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci, 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 @@ -1993,16 +1998,22 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci, 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 (numCCE <= get_nCCE(1, frame_parms, get_mi(frame_parms, subframe))) + if (CCE_max_used_index < get_nCCE(1, frame_parms, get_mi(frame_parms, subframe))) return(cmax(1,nCCEmin)); //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 4 : 5))) - else if (numCCE <= get_nCCE(2, frame_parms, get_mi(frame_parms, subframe))) + else if (CCE_max_used_index < get_nCCE(2, frame_parms, get_mi(frame_parms, subframe))) return(cmax(2,nCCEmin)); //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 7 : 8))) - else if (numCCE <= get_nCCE(3, frame_parms, get_mi(frame_parms, subframe))) + else if (CCE_max_used_index < get_nCCE(3, frame_parms, get_mi(frame_parms, subframe))) return(cmax(3,nCCEmin)); else if (frame_parms->N_RB_DL<=10) { if (frame_parms->Ncp == 0) { // normal CP @@ -2503,7 +2514,7 @@ void dci_decoding(uint8_t DCI_LENGTH, } -static uint8_t dci_decoded_output[(MAX_DCI_SIZE_BITS+64)/8]; +static uint8_t dci_decoded_output[2][(MAX_DCI_SIZE_BITS+64)/8]; uint16_t get_nCCE(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uint8_t mi) { @@ -2795,21 +2806,23 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, #ifdef DEBUG_DCI_DECODING if (do_common == 1) - LOG_I(PHY,"[DCI search - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n",m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); + 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 - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n",m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); + 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)\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); #endif dci_decoding(sizeof_bits, L, &pdcch_vars[eNB_id]->e_rx[CCEind*72], - dci_decoded_output); + &dci_decoded_output[subframe&0x1][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,sizeof_bits)>>16) ^ extract_crc(dci_decoded_output,sizeof_bits); + crc = (crc16(&dci_decoded_output[subframe&0x1][0],sizeof_bits)>>16) ^ extract_crc(&dci_decoded_output[subframe&0x1][0],sizeof_bits); #ifdef DEBUG_DCI_DECODING printf("crc =>%x\n",crc); #endif @@ -2823,27 +2836,31 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, 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[0]; - dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[1]; - dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[2]; - dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[3]; + dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[subframe&0x1][0]; + dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[subframe&0x1][1]; + dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[subframe&0x1][2]; + dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[subframe&0x1][3]; #ifdef DEBUG_DCI_DECODING - printf("DCI => %x,%x,%x,%x\n",dci_decoded_output[0],dci_decoded_output[1],dci_decoded_output[2],dci_decoded_output[3]); + printf("DCI => %x,%x,%x,%x\n",dci_decoded_output[subframe&0x1][0], + dci_decoded_output[subframe&0x1][1], + dci_decoded_output[subframe&0x1][2], + dci_decoded_output[subframe&0x1][3]); #endif } else { - dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[0]; - dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[1]; - dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[2]; - dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[3]; - dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[4]; - dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[5]; - dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[6]; - dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[7]; + dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[subframe&0x1][0]; + dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[subframe&0x1][1]; + dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[subframe&0x1][2]; + dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[subframe&0x1][3]; + dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[subframe&0x1][4]; + dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[subframe&0x1][5]; + dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[subframe&0x1][6]; + dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[subframe&0x1][7]; #ifdef DEBUG_DCI_DECODING printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", - dci_decoded_output[0],dci_decoded_output[1],dci_decoded_output[2],dci_decoded_output[3], - dci_decoded_output[4],dci_decoded_output[5],dci_decoded_output[6],dci_decoded_output[7]); + dci_decoded_output[subframe&0x1][0],dci_decoded_output[subframe&0x1][1],dci_decoded_output[subframe&0x1][2],dci_decoded_output[subframe&0x1][3], + dci_decoded_output[subframe&0x1][4],dci_decoded_output[subframe&0x1][5],dci_decoded_output[subframe&0x1][6],dci_decoded_output[subframe&0x1][7]); #endif } @@ -2860,7 +2877,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, *dci_cnt = *dci_cnt+1; } else if (crc==pdcch_vars[eNB_id]->crnti) { - if ((mode&UL_DCI)&&(format_c == format0)&&((dci_decoded_output[0]&0x80)==0)) {// check if pdu is format 0 or 1A + if ((mode&UL_DCI)&&(format_c == format0)&&((dci_decoded_output[subframe&0x1][0]&0x80)==0)) {// check if pdu is format 0 or 1A if (*format0_found == 0) { dci_alloc[*dci_cnt].format = format0; *format0_found = 1; @@ -2893,15 +2910,15 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, break; case 2: - *CCEmap|=(0x03<<(CCEind&0x1f)); + *CCEmap|=(1<<(CCEind&0x1f)); break; case 4: - *CCEmap|=(0x0f<<(CCEind&0x1f)); + *CCEmap|=(1<<(CCEind&0x1f)); break; case 8: - *CCEmap|=(0xff<<(CCEind&0x1f)); + *CCEmap|=(1<<(CCEind&0x1f)); break; } @@ -2928,7 +2945,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, uint8_t dci_cnt=0,old_dci_cnt=0; uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; - LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars; + LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars[subframe & 0x1]; LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; uint8_t mi = get_mi(&ue->frame_parms,subframe); uint16_t ra_rnti=99; @@ -3149,7 +3166,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0) , ra_rnti, P_RNTI, 2, @@ -3177,7 +3194,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, @@ -3209,7 +3226,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), P_RNTI, ra_rnti, 3, @@ -3237,7 +3254,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, @@ -3271,7 +3288,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, @@ -3300,7 +3317,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, @@ -3333,7 +3350,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, @@ -3362,7 +3379,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, @@ -3395,7 +3412,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, @@ -3426,7 +3443,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, @@ -3458,7 +3475,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, @@ -3490,7 +3507,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, @@ -3518,16 +3535,18 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, } 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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, - P_RNTI, + P_RNTI, 0, format1A, format1A, @@ -3542,21 +3561,25 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, &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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, @@ -3577,19 +3600,22 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, ((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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, - P_RNTI, + P_RNTI, 2, format1A, format1A, @@ -3608,18 +3634,21 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, ((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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, @@ -3636,16 +3665,24 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, &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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, @@ -3670,13 +3707,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, 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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, @@ -3701,13 +3739,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, 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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, @@ -3733,13 +3772,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, //#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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, @@ -3762,13 +3802,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, #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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, @@ -3794,13 +3835,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, 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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, @@ -3825,13 +3867,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, 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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, @@ -3858,13 +3901,14 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, //#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, subframe, dci_alloc, eNB_id, frame_parms, mi, - SI_RNTI, + ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, diff --git a/openair1/PHY/LTE_TRANSPORT/dci.h b/openair1/PHY/LTE_TRANSPORT/dci.h index 74c150ccab7a43a5ae8444de686d5e2a15fcc1be..a9a5dda29ef14f5fd7475469f513809b5be112dd 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.h +++ b/openair1/PHY/LTE_TRANSPORT/dci.h @@ -230,7 +230,7 @@ typedef struct DCI1A_10MHz_TDD_1_6 DCI1A_10MHz_TDD_1_6_t; /// DCI Format Type 0 (20 MHz,TDD1-6, 27 bits) struct DCI0_20MHz_TDD_1_6 { /// Padding - uint32_t padding:2; + uint32_t padding:3; /// CQI request uint32_t cqi_req:1; /// DAI @@ -1897,9 +1897,9 @@ struct DCI2A_10MHz_4A_TDD { #define sizeof_DCI2A_10MHz_4A_TDD_t 41 typedef struct DCI2A_10MHz_4A_TDD DCI2A_10MHz_4A_TDD_t; -/// DCI Format Type 2A (10 MHz, FDD, 2 Antenna Ports, 36 bits) +/// DCI Format Type 2A (10 MHz, FDD, 2 Antenna Ports, 40 bits) struct DCI2A_10MHz_2A_FDD { - uint64_t padding:28; + uint64_t padding:24; /// Redundancy version 2 uint64_t rv2:2; /// New Data Indicator 2 @@ -1923,7 +1923,7 @@ struct DCI2A_10MHz_2A_FDD { /// Resource Allocation Header uint64_t rah:1; } __attribute__ ((__packed__)); -#define sizeof_DCI2A_10MHz_2A_FDD_t 36 +#define sizeof_DCI2A_10MHz_2A_FDD_t 41 typedef struct DCI2A_10MHz_2A_FDD DCI2A_10MHz_2A_FDD_t; /// DCI Format Type 2A (10 MHz, FDD, 4 Antenna Ports, 38 bits) @@ -2969,3 +2969,53 @@ struct DCI0A_20_MHz { #define sizeof_DCI0A_20MHz 17 #define MAX_DCI_SIZE_BITS 45 + +struct DCI_INFO_EXTRACTED { + /// type = 0 => DCI Format 0, type = 1 => DCI Format 1A + uint8_t type; + /// Resource Allocation Header + uint8_t rah; + /// HARQ Process + uint8_t harq_pid; + /// CQI Request + uint8_t cqi_req; + /// SRS Request + uint8_t srs_req; + /// Power Control + uint8_t TPC; + /// Localized/Distributed VRB + uint8_t vrb_type; + /// RB Assignment (ceil(log2(N_RB_DL/P)) bits) + uint32_t rballoc; + // Applicable only when vrb_type = 1 + uint8_t Ngap; + /// Cyclic shift + uint8_t cshift; + /// Hopping flag + uint8_t hopping; + /// Downlink Assignment Index + uint8_t dai; + /// DAI (TDD) + uint8_t ulindex; + + /// TB swap + uint8_t tb_swap; + /// TPMI information for precoding + uint8_t tpmi; + /// Redundancy version 2 + uint8_t rv2; + /// New Data Indicator 2 + uint8_t ndi2; + /// Modulation and Coding Scheme and Redundancy Version 2 + uint8_t mcs2; + /// Redundancy version 1 + uint8_t rv1; + /// New Data Indicator 1 + uint8_t ndi1; + /// Modulation and Coding Scheme and Redundancy Version 1 + uint8_t mcs1; + + /// Scrambling ID + uint64_t ap_si_nl_id:3; +}; +typedef struct DCI_INFO_EXTRACTED DCI_INFO_EXTRACTED_t; diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 72f276408fd934376796230fcef038240e402f39..59d16c7a39af3a1e839c3dc4bbd60542bb75f1c4 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -37,6 +37,9 @@ #endif #include "assertions.h" + +//#define DEBUG_HARQ + #include "LAYER2/MAC/extern.h" #include "LAYER2/MAC/defs.h" @@ -399,7 +402,7 @@ uint16_t computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs) } // Convert a DCI Format 1C RIV to a Format 1A RIV -// This extracts the start and length in PRBs from the 1C rballoc and +// 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) { @@ -443,7 +446,7 @@ uint32_t conv_1C_RIV(int32_t rballoc,uint32_t N_RB_DL) { } // 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) { @@ -451,11 +454,11 @@ 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: @@ -466,19 +469,19 @@ uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap) { return ((3*odd_slot) + 2*(vrb&3) + 5)%6; break; case 4: // even: 4->1, odd: 4->4 - return ((3*odd_slot) + 1)%6; + 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); + 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); + return (((7*odd_slot) + 4*(vrb&3) + (vrb>>2) +13 )%14) + 14*(vrb/14); } if (vrb==12) return (3+(7*odd_slot)) % 14; @@ -486,71 +489,71 @@ uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap) { 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; + offset=4; else - offset=0; + 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&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); + return offset+((23*odd_slot) + 22-12+1); if (vrb==45) // even: 45->10, odd: 45->33 - return offset+((23*odd_slot) + 22+12); + return offset+((23*odd_slot) + 22+12); if (vrb==46) - return offset+46+((23*odd_slot) + 23-12+1) % 46; + return offset+46+((23*odd_slot) + 23-12+1) % 46; if (vrb==47) - return offset+46+((23*odd_slot) + 23+12) % 46; + return offset+46+((23*odd_slot) + 23+12) % 46; if (vrb==48) - return offset+46+((23*odd_slot) + 23-12+1) % 46; + return offset+46+((23*odd_slot) + 23-12+1) % 46; if (vrb==49) - return offset+46+((23*odd_slot) + 23+12) % 46; + return offset+46+((23*odd_slot) + 23+12) % 46; } else { // Nrow=6,Nnull=6,NVRBDL=18,Ngap1= 27 if (vrb>=9) - offset=18; + offset=18; else - offset=0; - + 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; + 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); + 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); + 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); + 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); + 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); + return ((16*odd_slot) + 8*(vrb&3) + (vrb>>2))%32 + (vrb/32); } break; default: @@ -558,7 +561,7 @@ uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap) { return 0; } return 0; - + } @@ -737,7 +740,7 @@ void generate_RIV_tables() 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); +// printf("nVRB %d => nVRB_even_dist %d\n",nVRB,nVRB_even_dist); if (nVRB_even_dist<32) @@ -745,16 +748,16 @@ void generate_RIV_tables() 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)); + allocdist2_0_even |= (1<<(nVRB_even_dist-64)); else - allocdist3_0_even |= (1<<(nVRB_even_dist-96)); + 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 - ); + 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); @@ -763,9 +766,9 @@ void generate_RIV_tables() 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)); + allocdist2_0_odd |= (1<<(nVRB_odd_dist-64)); else - allocdist3_0_odd |= (1<<(nVRB_odd_dist-96)); + allocdist3_0_odd |= (1<<(nVRB_odd_dist-96)); // Distributed Gap2, even slot @@ -775,9 +778,9 @@ void generate_RIV_tables() 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)); + allocdist2_1_even |= (1<<(nVRB_even_dist-64)); else - allocdist3_1_even |= (1<<(nVRB_even_dist-96)); + allocdist3_1_even |= (1<<(nVRB_even_dist-96)); // Distributed Gap2, odd slot @@ -787,9 +790,9 @@ void generate_RIV_tables() 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)); + allocdist2_1_odd |= (1<<(nVRB_odd_dist-64)); else - allocdist3_1_odd |= (1<<(nVRB_odd_dist-96)); + allocdist3_1_odd |= (1<<(nVRB_odd_dist-96)); RIV=computeRIV(100,RBstart,Lcrbs); @@ -855,7 +858,7 @@ uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti) } int generate_eNB_dlsch_params_from_dci(int frame, - uint8_t subframe, + uint8_t subframe, void *dci_pdu, uint16_t rnti, DCI_format_t dci_format, @@ -866,14 +869,14 @@ int generate_eNB_dlsch_params_from_dci(int frame, uint16_t ra_rnti, uint16_t p_rnti, uint16_t DL_pmi_single, - uint8_t beamforming_mode) + 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; + 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; @@ -881,6 +884,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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); @@ -921,13 +925,14 @@ int generate_eNB_dlsch_params_from_dci(int frame, } dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch0_harq->codeword=0; if (vrb_type==LOCALIZED) { - dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rballoc]; + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rballoc]; } else { - LOG_E(PHY,"Distributed RB allocation not done yet\n"); - mac_xface->macphy_exit("exiting"); + 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; @@ -959,13 +964,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - + if (vrb_type==LOCALIZED) { - dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rballoc]; + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rballoc]; } else { - LOG_E(PHY,"Distributed RB allocation not done yet\n"); - mac_xface->macphy_exit("exiting"); + 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; @@ -994,12 +999,12 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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]; + 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"); + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); } @@ -1031,14 +1036,14 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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]; + 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"); + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); } @@ -1211,6 +1216,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, } 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; @@ -1240,7 +1246,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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) { @@ -1283,12 +1289,12 @@ int generate_eNB_dlsch_params_from_dci(int frame, break; - case format2: + case format2: // DL Scheduling assignment for MIMO including closed loop spatial multiplexing switch (frame_parms->N_RB_DL) { case 6: - if (frame_parms->nb_antennas_tx == 2) { + 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; @@ -1308,7 +1314,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx == 4) { + } 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; @@ -1329,13 +1335,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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_antennas_tx == 2) { + 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; @@ -1357,7 +1363,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, tbswap = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap; tpmi = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi; } - } else if (frame_parms->nb_antennas_tx == 4) { + } 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; @@ -1380,13 +1386,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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_antennas_tx == 2) { + 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; @@ -1408,7 +1414,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, tbswap = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap; tpmi = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tpmi; } - } else if (frame_parms->nb_antennas_tx == 4) { + } 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; @@ -1431,13 +1437,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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_antennas_tx == 2) { + 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; @@ -1459,7 +1465,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, tbswap = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap; tpmi = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tpmi; } - } else if (frame_parms->nb_antennas_tx == 4) { + } 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; @@ -1482,7 +1488,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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; @@ -1497,149 +1503,240 @@ int generate_eNB_dlsch_params_from_dci(int frame, // 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 - if (tbswap == 0) { - dlsch0 = dlsch[0]; - dlsch1 = dlsch[1]; - } else { - dlsch0 = dlsch[1]; - dlsch1 = dlsch[0]; + 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("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 } - dlsch0_harq = dlsch0->harq_processes[harq_pid]; - dlsch1_harq = dlsch1->harq_processes[harq_pid]; + if (dlsch0 != NULL){ + dlsch0->subframe_tx[subframe] = 1; - dlsch0->subframe_tx[subframe] = 1; + dlsch0->current_harq_pid = harq_pid; + dlsch0->harq_ids[subframe] = harq_pid; + } - 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); + if (dlsch1_harq != NULL){ + dlsch1->current_harq_pid = harq_pid; + dlsch1->harq_ids[subframe] = harq_pid; + } - conv_rballoc(rah, - rballoc, - frame_parms->N_RB_DL, - dlsch0_harq->rb_alloc); + if (dlsch0 != NULL ){ + 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->nb_rb = conv_nprb(rah, rballoc, frame_parms->N_RB_DL); - if (dlsch0_harq->nb_rb == 0) - return(-1); + 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);*/ - 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; + 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 ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { - dlsch0->active = 0; - } - - if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { - dlsch1->active = 0; - } - if (frame_parms->nb_antennas_tx == 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]; + 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 = UNIFORM_PRECODING11; - dlsch1_harq->mimo_mode = UNIFORM_PRECODING1m1; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0); - dlsch1_harq->pmi_alloc = pmi_extend(frame_parms,1); + 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 = UNIFORM_PRECODING1j; - dlsch1_harq->mimo_mode = UNIFORM_PRECODING1mj; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2); - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3); - break; + 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; + dlsch0_harq->pmi_alloc = DL_pmi_single; dlsch1_harq->mimo_mode = DUALSTREAM_PUSCH_PRECODING; - dlsch1_harq->pmi_alloc = DL_pmi_single; + dlsch1_harq->pmi_alloc = DL_pmi_single; break; - default: break; } - - 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]; - } else { // only one is active + } 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); + 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); + 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); + 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); + 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; + dlsch0_harq->pmi_alloc = DL_pmi_single; break; - case 6: dlsch0_harq->mimo_mode = PUSCH_PRECODING1; - dlsch0_harq->pmi_alloc = DL_pmi_single; + 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; + } + } - dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; - } - } else if (frame_parms->nb_antennas_tx == 4) { + } 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) + /* if (dlsch0_harq->round == 0) dlsch0_harq->status = ACTIVE; if (dlsch1_harq->round == 0) - dlsch1_harq->status = ACTIVE; - - dlsch0->rnti = rnti; - dlsch1->rnti = rnti; - - dlsch0_harq->dl_power_off = 0; - dlsch1_harq->dl_power_off = 0; + dlsch1_harq->status = ACTIVE;*/ + if (dlsch0_harq != NULL) + dlsch0->rnti = rnti; + if (dlsch1 != NULL) + dlsch1->rnti = rnti; break; @@ -1648,7 +1745,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, switch (frame_parms->N_RB_DL) { case 6: - if (frame_parms->nb_antennas_tx == 2) { + 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; @@ -1666,7 +1763,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx == 4) { + } 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; @@ -1687,13 +1784,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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_antennas_tx == 2) { + 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; @@ -1713,7 +1810,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx == 4) { + } 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; @@ -1736,13 +1833,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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_antennas_tx == 2) { + 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; @@ -1762,7 +1859,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx == 4) { + } 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; @@ -1785,13 +1882,13 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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_antennas_tx == 2) { + 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; @@ -1811,7 +1908,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx == 4) { + } 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; @@ -1834,7 +1931,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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_antennas_tx); + 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; @@ -1849,6 +1946,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, // 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]; @@ -1904,15 +2002,16 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch1->active = 0; } - dlsch0_harq->dl_power_off = 0; - dlsch1_harq->dl_power_off = 0; + // dlsch0_harq->dl_power_off = 0; + // dlsch1_harq->dl_power_off = 0; - if (frame_parms->nb_antennas_tx == 2) { + 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; @@ -1921,7 +2020,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch0_harq->mimo_mode = ALAMOUTI; dlsch1_harq->mimo_mode = ALAMOUTI; } - } else if (frame_parms->nb_antennas_tx == 4) { // 4 antenna case + } 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 @@ -2004,7 +2103,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, } } } else { - LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antennas_tx); + 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 @@ -2133,16 +2232,21 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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; + 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; @@ -2293,6 +2397,10 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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, @@ -2336,14 +2444,14 @@ int generate_eNB_dlsch_params_from_dci(int frame, } // check TPMI information to compute TBS - if (frame_parms->nb_antennas_tx == 2) { + 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_antennas_tx == 4) { + } else if (frame_parms->nb_antenna_ports_eNB == 4) { } @@ -2465,6 +2573,10 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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, @@ -2546,6 +2658,8 @@ int generate_eNB_dlsch_params_from_dci(int frame, //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, @@ -2586,27 +2700,30 @@ int generate_eNB_dlsch_params_from_dci(int frame, case 1: dlsch0_harq->mimo_mode = UNIFORM_PRECODING11; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0); + 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); + 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); + 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); + 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; + dlsch0_harq->pmi_alloc = DL_pmi_single; break; case 6: @@ -2652,7 +2769,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, break; } - + if (dlsch0_harq) { dlsch0_harq->frame = frame; dlsch0_harq->subframe = subframe; @@ -2678,12 +2795,33 @@ int generate_eNB_dlsch_params_from_dci(int frame, 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 - computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off); + 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); } @@ -3074,45 +3212,45 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) 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)]); + ((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_antennas_tx == 2) { + 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", @@ -3195,7 +3333,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) DevParam (frame_parms->N_RB_DL, 0, 0); break; } - } else if (frame_parms->nb_antennas_tx == 4) { + } 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", @@ -3280,7 +3418,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) } } } else if (frame_parms->frame_type == FDD) { - if (frame_parms->nb_antennas_tx == 2) { + 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", @@ -3300,7 +3438,9 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) break; case 25: - LOG_D(PHY,"DCI format2 2 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", + + 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, @@ -3358,7 +3498,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) DevParam (frame_parms->N_RB_DL, 0, 0); break; } - } else if (frame_parms->nb_antennas_tx == 4) { + } else if (frame_parms->nb_antenna_ports_eNB == 4) { switch(frame_parms->N_RB_DL) { case 6: @@ -3801,1860 +3941,2495 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci) } -int generate_ue_dlsch_params_from_dci(int frame, - uint8_t subframe, - void *dci_pdu, - uint16_t rnti, - DCI_format_t dci_format, - LTE_UE_DLSCH_t **dlsch, - LTE_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) +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 harq_pid=0; - uint32_t rballoc=0,RIV_max=0; - uint8_t frame_type=frame_parms->frame_type; - uint8_t vrb_type=0; - uint8_t mcs=0,mcs1=0,mcs2=0; - uint8_t rv=0,rv1=0,rv2=0; - uint8_t ndi=0,ndi1=0,ndi2=0; - uint8_t rah=0; - uint8_t TPC=0; - uint8_t NPRB=0,tbswap=0,tpmi=0; - uint8_t Ngap; - uint8_t dai=0; - LTE_UE_DLSCH_t *dlsch0=NULL,*dlsch1=NULL; - LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_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, - subframe, - (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 + uint8_t dai=0; - switch (dci_format) { + 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 format0: // This is an ULSCH allocation so nothing here, inform MAC - LOG_E(PHY,"format0 not possible\n"); - return(-1); - break; + case 25: - case format1A: + 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); + } - 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; - 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; - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { // - harq_pid = 0; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - // see 36-212 V8.6.0 p. 45 - NPRB = (TPC&1) + 2; - } else { + 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; - if (harq_pid>=8) { - LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid); - return(-1); + 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; + } - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - NPRB = RIV2nb_rb_LUT6[rballoc]; - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; - } + 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; +} - if (vrb_type == LOCALIZED) { - dlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT6[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT6[rballoc]; - } - else { - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT6[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT6[rballoc]; - } - dlsch0_harq->vrb_type = vrb_type; +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; - dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rballoc];//NPRB; - RIV_max = RIV_max6; + 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; + break; - case 25: + case 25: + mcs = ((DCI1C_5MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_5MHz_t *)dci_pdu)->rballoc,6); - 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); - } - - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { // - harq_pid = 0; - // see 36-212 V8.6.0 p. 45 - NPRB = (TPC&1) + 2; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - } else { - - if (harq_pid>=8) { - LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid); - return(-1); - } - - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - NPRB = RIV2nb_rb_LUT25[rballoc]; - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; - } - - if (vrb_type == LOCALIZED) { - dlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT25[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT25[rballoc]; - } - else { - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT25[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT25[rballoc]; - } - dlsch0_harq->vrb_type = vrb_type; - dlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rballoc]; - RIV_max = RIV_max25; + break; - break; + case 50: + mcs = ((DCI1C_10MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_10MHz_t *)dci_pdu)->rballoc,6); - 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; - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { // - harq_pid = 0; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - // see 36-212 V8.6.0 p. 45 - NPRB = (TPC&1) + 2; - } else { + case 100: + mcs = ((DCI1C_20MHz_t *)dci_pdu)->mcs; + rballoc = conv_1C_RIV(((DCI1C_20MHz_t *)dci_pdu)->rballoc,6); + break; - if (harq_pid>=8) { - LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid); - return(-1); + default: + AssertFatal(0,"Format 1C: Unknown N_RB_DL %d\n",N_RB_DL); + break; } - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - NPRB = RIV2nb_rb_LUT50[rballoc]; - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; - } - - if (vrb_type == LOCALIZED) { - dlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = localRIV2alloc_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = localRIV2alloc_LUT50_1[rballoc]; - // printf("rballoc: %08x.%08x\n",dlsch0_harq->rb_alloc_even[0],dlsch0_harq->rb_alloc_even[1]); - } else { // DISTRIBUTED - if ((rballoc&(1<<10)) == 0) { - rballoc = rballoc&(~(1<<10)); - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; - } - else { - rballoc = rballoc&(~(1<<10)); - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; - } - } - dlsch0_harq->vrb_type = vrb_type; - - dlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rballoc];//NPRB; - RIV_max = RIV_max50; - break; + pdci_info_extarcted->mcs1 = mcs; + pdci_info_extarcted->rballoc = rballoc; +} - 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); - } +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) +{ - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { // - harq_pid = 0; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - // see 36-212 V8.6.0 p. 45 - NPRB = (TPC&1) + 2; - } else { + 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; - if (harq_pid>=8) { - LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid); - return(-1); + 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; } - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - NPRB = RIV2nb_rb_LUT100[rballoc]; - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; - } - - if (vrb_type == LOCALIZED) { - dlsch0_harq->rb_alloc_even[0] = localRIV2alloc_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = localRIV2alloc_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_even[2] = localRIV2alloc_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_even[3] = localRIV2alloc_LUT100_3[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = localRIV2alloc_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = localRIV2alloc_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[2] = localRIV2alloc_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_odd[3] = localRIV2alloc_LUT100_3[rballoc]; - } else { - if ((rballoc&(1<<10)) == 0) { //Gap 1 - rballoc = rballoc&(~(1<<12)); - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap0_even_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap0_even_LUT100_3[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap0_odd_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap0_odd_LUT100_3[rballoc]; - } - else { //Gap 2 - rballoc = rballoc&(~(1<<12)); - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap1_even_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap1_even_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap1_even_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap1_even_LUT100_3[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap1_odd_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap1_odd_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap1_odd_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap1_odd_LUT100_3[rballoc]; - } - } - dlsch0_harq->vrb_type = vrb_type; - - dlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rballoc];//NPRB; - RIV_max = RIV_max100; - break; - } - - if (rballoc>RIV_max) { - LOG_E(PHY,"Format 1A: rb_alloc > RIV_max\n"); - return(-1); - } - - if (NPRB==0) { - LOG_E(PHY,"Format 1A: NPRB=0\n"); - return(-1); - } - - if((mcs>28) && ( (dlsch0_harq->round == 0) || (rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti) )) - { - // DCI false detection - return(-1); - } - if((rv!=0) && (dlsch0_harq->round == 0) && (rnti != si_rnti) && (rnti != p_rnti) && (rnti != ra_rnti)) - { - // DCI false detection - return(-1); - } - - // change the mcs limit from 7 to 8, supported by MAC - /* if (mcs > 10) { - LOG_E(PHY,"Format 1A: subframe %d unlikely mcs for format 1A (%d), TPC %d rv %d\n",subframe,mcs,TPC,rv); - return(-1); - }*/ - - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { // - // if ((dlsch0_harq->round == 4) || ( { - dlsch0_harq->round = 0; - dlsch0_harq->first_tx = 1; - // } - - // if (dlsch0_harq->round == 0) - // ndi = 1-dlsch0_harq->DCINdi; - } + break; - dlsch[0]->current_harq_pid = harq_pid; + 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; + } - dlsch0_harq->rvidx = rv; - dlsch0_harq->Nl = 1; - // dlsch[0]->layer_index = 0; + break; - dlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI; - dlsch0_harq->dl_power_off = 1; //no power offset + 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; + } - dlsch[0]->active = 1; // fix no DLSCH decoding for downlink retransmission + break; - if ((ndi!=dlsch0_harq->DCINdi) || // DCI has been toggled or this is the first transmission - (dlsch0_harq->first_tx==1)) { - dlsch0_harq->round = 0; + 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; + } - if (dlsch0_harq->first_tx==1) { - //LOG_I(PHY,"[PDSCH %x/%d] Format 1A DCI First TX: Clearing flag\n"); - dlsch0_harq->first_tx = 0; - } - } else if (dlsch0_harq->round == 0) { // duplicated PDSCH received. possibly eNB missed the previous DL ACK/NACK feedback - - // skip PDSCH decoding - dlsch[0]->active = 0; - // report ACK back to eNB for this duplicated PDSCH - dlsch0_harq->status = SCH_IDLE; - dlsch0_harq->round = 0; - dlsch[0]->harq_ack[subframe].ack = 1; - dlsch[0]->harq_ack[subframe].harq_id = harq_pid; - dlsch[0]->harq_ack[subframe].send_harq_status = 1; - LOG_D(PHY,"UE (%x/%d): Format1A DCI: Duplicated PDSCH. Setting ACK for subframe %d (pid %d, round 0)\n", - dlsch[0]->rnti,harq_pid, subframe,harq_pid); - } - - LOG_D(PHY,"UE (%x/%d): SFN/SF %4d/%1d Format1A DCI: dai %d, ndi %d, old_ndi %d (first tx %d), harq_status %d, round %d\n", - rnti, - harq_pid, - frame % 1024, - subframe, - dai, - ndi, - dlsch0_harq->DCINdi, - dlsch0_harq->first_tx, - dlsch0_harq->status, - dlsch0_harq->round); - - if (rnti == tc_rnti) { - dlsch0_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,dlsch0_harq->DCINdi); - } else { - dlsch0_harq->DCINdi = ndi; + break; } - dlsch[0]->harq_ack[subframe].vDAI_DL = dai+1; - // this a retransmission - if(dlsch0_harq->round) - { - // compare old TBS to new TBS - if((mcs<29) && (dlsch0_harq->TBS != TBStable[get_I_TBS(mcs)][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"); - dlsch0_harq->round = 0; - } - } + 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; - if(mcs<29) - { - dlsch0_harq->mcs = mcs; - } +} - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { - dlsch0_harq->TBS = TBStable[mcs][NPRB-1]; - dlsch0_harq->Qm = 2; - } - else { - if(mcs < 29) - dlsch0_harq->TBS = TBStable[get_I_TBS(mcs)][NPRB-1]; - dlsch0_harq->Qm = get_Qm(mcs); - } - dlsch[0]->rnti = rnti; - dlsch0 = dlsch[0]; - //printf("Format 1A: harq_pid %d, nb_rb %d, round %d\n",harq_pid,dlsch0_harq->nb_rb,dlsch0_harq->round); - break; +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) +{ - case format1C: + 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) { - harq_pid = 0; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - - switch (frame_parms->N_RB_DL) { case 6: - mcs = ((DCI1C_1_5MHz_t *)dci_pdu)->mcs; - rballoc = conv_1C_RIV(((DCI1C_1_5MHz_t *)dci_pdu)->rballoc,6); - dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rballoc]; - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT6[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT6[rballoc]; - RIV_max = RIV_max6; + 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; + break; case 25: - mcs = ((DCI1C_5MHz_t *)dci_pdu)->mcs; - rballoc = conv_1C_RIV(((DCI1C_5MHz_t *)dci_pdu)->rballoc,25); - dlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rballoc]; - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_even_LUT25[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_odd_LUT25[rballoc]; - RIV_max = RIV_max25; - - // printf("Format1C : %x : mcs %d, rballoc %d=>%d=>%x\n",((uint32_t*)dci_pdu)[0], - // mcs,((DCI1C_5MHz_t *)dci_pdu)->rballoc,rballoc,dlsch0_harq->rb_alloc_even[0]); - break; + 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: - mcs = ((DCI1C_10MHz_t *)dci_pdu)->mcs; - rballoc = conv_1C_RIV(((DCI1C_10MHz_t *)dci_pdu)->rballoc,50); - Ngap = ((DCI1C_10MHz_t *)dci_pdu)->Ngap; - dlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rballoc]; - if (Ngap == 0) { - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT50_1[rballoc]; - } - else { - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap1_even_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap1_odd_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap1_even_LUT50_1[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap1_odd_LUT50_1[rballoc]; - } - RIV_max = RIV_max50; + 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; + break; case 100: - mcs = ((DCI1C_20MHz_t *)dci_pdu)->mcs; - rballoc = conv_1C_RIV(((DCI1C_20MHz_t *)dci_pdu)->rballoc,100); - Ngap = ((DCI1C_20MHz_t *)dci_pdu)->Ngap; - dlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rballoc]; - if (Ngap==0) { - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap0_even_LUT100_0[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap0_odd_LUT100_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap0_even_LUT100_1[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap0_odd_LUT100_1[rballoc]; - dlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap0_even_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap0_odd_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap0_even_LUT100_3[rballoc]; - dlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap0_odd_LUT100_3[rballoc]; - } - else { - dlsch0_harq->rb_alloc_even[0] = distRIV2alloc_gap1_even_LUT100_0[rballoc]; - dlsch0_harq->rb_alloc_odd[0] = distRIV2alloc_gap1_odd_LUT100_0[rballoc]; - dlsch0_harq->rb_alloc_even[1] = distRIV2alloc_gap1_even_LUT100_1[rballoc]; - dlsch0_harq->rb_alloc_odd[1] = distRIV2alloc_gap1_odd_LUT100_1[rballoc]; - dlsch0_harq->rb_alloc_even[2] = distRIV2alloc_gap1_even_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_odd[2] = distRIV2alloc_gap1_odd_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc_even[3] = distRIV2alloc_gap1_even_LUT100_3[rballoc]; - dlsch0_harq->rb_alloc_odd[3] = distRIV2alloc_gap1_odd_LUT100_3[rballoc]; - } - RIV_max = RIV_max100; - /* - printf("Format1C : %x : mcs %d, rballoc %d=>%d=>(%08x.%08x.%08x.%08x), Ngap %d\n",((uint32_t*)dci_pdu)[0], - mcs,((DCI1C_20MHz_t *)dci_pdu)->rballoc,rballoc, - dlsch0_harq->rb_alloc_even[0], - dlsch0_harq->rb_alloc_even[1], - dlsch0_harq->rb_alloc_even[2], - dlsch0_harq->rb_alloc_even[3], - Ngap - ); - */ - break; - - default: - LOG_E(PHY,"Format 1C: Unknown N_RB_DL %d\n",frame_parms->N_RB_DL); - return(-1); - break; - } - if (rballoc>RIV_max) { - LOG_E(PHY,"Format 1C: rb_alloc > RIV_max\n"); - return(-1); - } - - dlsch0_harq->round = 0; - dlsch0_harq->first_tx = 1; - dlsch0_harq->vrb_type = DISTRIBUTED; - dlsch[0]->current_harq_pid = harq_pid; + 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); + } - if (rnti==si_rnti) { // rule from Section 5.3.1 of 36.321 - if (((frame&1) == 0) && (subframe == 5)) - dlsch0_harq->rvidx = (((3*((frame>>1)&3))+1)>>1)&3; // SIB1 - else - dlsch0_harq->rvidx = (((3*(subframe&3))+1)>>1)&3; // other SIBs - } - else if ((rnti==p_rnti) || (rnti==ra_rnti)) { // Section 7.1.7.3 - dlsch0_harq->rvidx = 0; + 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; - dlsch0_harq->Nl = 1; - dlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI; - dlsch0_harq->dl_power_off = 1; //no power offset +} - LOG_D(PHY,"UE (%x/%d): Subframe %d Format1C DCI: harq_status %d, round %d\n", - dlsch[0]->rnti, - harq_pid, - subframe, - dlsch0_harq->status, - dlsch0_harq->round); +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) +{ - dlsch0_harq->mcs = mcs; + 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) { - dlsch0_harq->TBS = TBStable1C[mcs]; - dlsch0_harq->Qm = 2; - dlsch[0]->rnti = rnti; - dlsch[0]->active = 1; - dlsch0 = dlsch[0]; - break; + 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; + } + } - 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; - 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; + 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; + 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 (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; + 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 (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; + 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; } - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + 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; +} - if (harq_pid>=8) { - LOG_E(PHY,"Format 1: harq_pid=%d >= 8\n", harq_pid); - return(-1); +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 subframe, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + LTE_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, subframe, 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((mcs>28) && (dlsch0_harq->round == 0) ) + if(harq_pid>=8) { - // DCI false detection - return(-1); + LOG_I(PHY,"bad harq id \n"); + return(0); } - if((rv!=0) && (dlsch0_harq->round == 0) ) + if(dci_format == format1 && ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) ) { - // DCI false detection - return(-1); + LOG_I(PHY,"bad dci format \n"); + return(0); } - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; + if( mcs1 > 28) + { + if(pdlsch0_harq->round == 0) + { + LOG_I(PHY,"bad dci mcs + round \n"); + return(0); + } - dlsch[0]->current_harq_pid = harq_pid; - dlsch[0]->harq_ack[subframe].harq_id = harq_pid; + if((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + LOG_I(PHY,"bad dci mcs + rnti \n"); + return(0); + } + } - 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 ((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; + } + } - dlsch0_harq->nb_rb = conv_nprb(rah, - rballoc, - frame_parms->N_RB_DL); - NPRB = dlsch0_harq->nb_rb; + if(dci_format == format1) + { + NPRB = conv_nprb(rah, rballoc, N_RB_DL); + } - // printf("test PDSCH NPRB %d, rah %d, rballoc %x, rballoc2 %x\n",NPRB,rah,rballoc,dlsch0_harq->rb_alloc[0]); - if (NPRB==0) { - LOG_E(PHY,"Format 1: NPRB=0 (rballoc %x,mcs %d, frame_type %d N_RB_DL %d)\n",rballoc,mcs,frame_parms->frame_type,frame_parms->N_RB_DL); - return(-1); + 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); + } - if (TPC!=1) - LOG_D(PHY,"format1 TPC %d, dlsch0_harq->delta_PUCCH %d\n",TPC,dlsch0_harq->delta_PUCCH); - - dlsch0_harq->rvidx = rv; + // 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 + } + } - dlsch0_harq->Nl = 1; - // dlsch[0]->layer_index = 0; + return(1); +} - dlsch0_harq->dl_power_off = 1; //no power offset +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, + LTE_DL_UE_HARQ_t *pdlsch0_harq) +{ + uint32_t rballoc = pdci_info_extarcted->rballoc; - LOG_D(PHY,"UE (%x/%d): Subframe %d Format1 DCI: ndi %d, old_ndi %d (first tx %d) harq_status %d\n",dlsch[0]->rnti,harq_pid,subframe,ndi,dlsch0_harq->DCINdi, - dlsch0_harq->first_tx,dlsch0_harq->status); + uint8_t NPRB = 0; + uint32_t RIV_max = 0; - if ((ndi!=dlsch0_harq->DCINdi)|| - (dlsch0_harq->first_tx==1)) { - // printf("Rate: setting round to zero (ndi %d, DCINdi %d,first_tx %d)\n",ndi,dlsch0_harq->DCINdi,dlsch0_harq->first_tx); - dlsch0_harq->round=0; - dlsch0_harq->status = ACTIVE; - dlsch0_harq->DCINdi = ndi; + // I- check dci content minimum coherency - dlsch[0]->harq_ack[subframe].send_harq_status = 1; - if (dlsch0_harq->first_tx==1) { - LOG_D(PHY,"[PDSCH %x/%d] Format 1 DCI First TX: Clearing flag\n",rnti,harq_pid); - dlsch0_harq->first_tx = 0; - } + 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; } - dlsch0_harq->mcs = mcs; + if(rballoc > RIV_max) + { + // DCI false detection + return(0); + } + + if(NPRB == 0) + { + // DCI false detection + return(0); + } - // this a retransmission - if(dlsch0_harq->round) + 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, + LTE_DL_UE_HARQ_t *pdlsch0_harq, + LTE_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) { - // compare old TBS to new TBS - if(dlsch0_harq->TBS != TBStable[get_I_TBS(mcs)][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,"Format1 Retransmission but TBS are different: consider it as new transmission !!! \n"); - dlsch0_harq->round = 0; - } + LOG_I(PHY,"bad harq pid\n"); + return(0); } - dlsch0_harq->TBS = TBStable[get_I_TBS(mcs)][NPRB-1]; - if (mcs <= 28) - dlsch0_harq->Qm = get_Qm(mcs); - else if (mcs<=31) - dlsch0_harq->Qm = (mcs-28)<<1; - else - LOG_E(PHY,"invalid mcs %d\n",mcs); - // printf("test: MCS %d, NPRB %d, TBS %d\n",mcs,NPRB,dlsch0_harq->TBS); - dlsch[0]->current_harq_pid = harq_pid; + if( (rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti) ) + { + LOG_I(PHY,"bad rnti\n"); + return(0); + } - dlsch[0]->active = 1; - dlsch[0]->rnti = rnti; + if( mcs1 > 28) + { + if(pdlsch0_harq->round == 0) + { + LOG_I(PHY,"bad mcs1\n"); + return(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,"Not supported beamforming mode %d\n",beamforming_mode); - + if( mcs2 > 28) + { + if(pdlsch1_harq->round == 0) + { + LOG_I(PHY,"bad mcs2\n"); + return(0); + } - dlsch0 = dlsch[0]; + } - break; + /* + if((pdlsch0_harq->round > 0) && (mcs1 != pdlsch0_harq->mcs)) + { + // DCI false detection + return(0); + }*/ - case format2: - switch (frame_parms->N_RB_DL) { + if((pdlsch0_harq->round == 0) && (rv1 > 0)) + { + // DCI false detection + LOG_I(PHY,"bad rv1\n"); + return(0); + } + + if((pdlsch1_harq->round == 0) && (rv2 > 0)) + { + // DCI false detection + LOG_I(PHY,"bad rv2\n"); + return(0); + } + + + switch (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; + if (rah == 0) + { + //RBG = 1; + RIV_max = 0x3F; } - } 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 + { + RIV_max = RIV_max6; } - } else { - LOG_E(PHY,"UE: subframe %d Format2 DCI: unsupported number of TX antennas %d\n",subframe,frame_parms->nb_antenna_ports_eNB); - } - - break; - + 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; + if (rah == 0) + { + //RBG = 2; + RIV_max = 0x1FFF; } - } 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 + { + RIV_max = RIV_max25; } - } else { - LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB); - } - - break; - + 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; + if (rah == 0) + { + //RBG = 3; + RIV_max = 0x1FFFF; } - } 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 + { + RIV_max = RIV_max50; } - } else { - LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB); - } - - break; - + 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; + if (rah == 0) + { + //RBG = 4; + RIV_max = 0x1FFFFFF; } - } 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 + { + RIV_max = RIV_max100; } - } else { - LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB); - } - - break; - } - - if (harq_pid>=8) { - LOG_E(PHY,"Format 2_2A: harq_pid=%d >= 8\n", harq_pid); - return(-1); + break; } + NPRB = conv_nprb(rah, + rballoc, + N_RB_DL); - dlsch[0]->current_harq_pid = harq_pid; - dlsch[0]->harq_ack[subframe].harq_id = harq_pid; - - tbswap = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->tb_swap; - 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]; - 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]; - - 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]; + if( (rballoc > RIV_max) && (rah == 1) ) + { + // DCI false detection + LOG_I(PHY,"bad rballoc %d RIV_max %lld\n", rballoc, RIV_max); + return(0); + } - dlsch0_harq->nb_rb = conv_nprb(rah, - rballoc, - frame_parms->N_RB_DL); - dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; + if(NPRB == 0) + { + // DCI false detection + LOG_I(PHY,"bad NPRB\n"); + return(0); + } - dlsch0_harq->mcs = mcs1; + return(1); +} - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; - /* - if (dlsch0_harq->mcs>20) { - printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); - return(-1); - } - */ +void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, + uint8_t N_RB_DL, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t subframe, + uint16_t rnti, + uint16_t tc_rnti, + uint16_t si_rnti, + uint16_t ra_rnti, + uint16_t p_rnti, + LTE_DL_UE_HARQ_t *pdlsch0_harq, + LTE_UE_DLSCH_t *pdlsch0) +{ - dlsch1_harq->mcs = mcs2; - dlsch0_harq->rvidx = rv1; - dlsch1_harq->rvidx = rv2; + 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; - // check if either TB is disabled (see 36-213 V8.6 p. 26) + uint8_t NPRB = 0; - if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { - dlsch0_harq->status = DISABLED; + if(dci_format == format1A) + { + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + NPRB = (TPC&1) + 2; + } + 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; + } + } } - - if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { - dlsch1_harq->status = DISABLED; + else // format1 + { + NPRB = conv_nprb(rah, rballoc, N_RB_DL); } - dlsch0_harq->Nl = 1; - - // dlsch0->layer_index = tbswap; - // dlsch1->layer_index = 1-tbswap; - - 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); - break; - - case 2: - dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1); - break; - - case 3: - dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2); - break; - - case 4: - dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3); - 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; + pdlsch0->current_harq_pid = harq_pid; + pdlsch0->active = 1; + pdlsch0->rnti = rnti; + if(dci_format == format1A) + pdlsch0->harq_ack[subframe].vDAI_DL = dai+1; - case 6: - dlsch0_harq->mimo_mode = PUSCH_PRECODING1; - LOG_E(PHY,"Unsupported TPMI\n"); - return(-1); - break; + if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) + { + pdlsch0_harq->round = 0; + pdlsch0_harq->first_tx = 1; + 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); + } + // DCI has been toggled or this is the first transmission + if (ndi1!=pdlsch0_harq->DCINdi) + { + pdlsch0_harq->round = 0; + pdlsch0_harq->first_tx = 1; + pdlsch0_harq->status = ACTIVE; + } - if (frame_parms->mode1_flag == 1) - dlsch0_harq->mimo_mode = SISO; - - if (ndi1!=dlsch0_harq->DCINdi) { - dlsch0_harq->round = 0; - dlsch0_harq->status = ACTIVE; - dlsch0_harq->DCINdi = ndi1; - } else if (dlsch0_harq->status == SCH_IDLE) { // we got an Ndi = 0 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); + if( ((ndi1 == pdlsch0_harq->DCINdi) && (pdlsch0_harq->round == 0)) || + ((rv1 != 0) && (pdlsch0_harq->round == 0)) + ) + { + 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[subframe].ack = 1; + pdlsch0->harq_ack[subframe].harq_id = harq_pid; + pdlsch0->harq_ack[subframe].send_harq_status = 1; + + pdlsch0_harq->first_tx = 0; + } } - dlsch0_harq->mcs = mcs1; + pdlsch0_harq->DCINdi = ndi1; + pdlsch0_harq->mcs = mcs1; + pdlsch0_harq->rvidx = rv1; + pdlsch0_harq->nb_rb = NPRB; - if (dlsch0_harq->nb_rb>1) { - dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1]; - if (mcs1 <= 28) - dlsch0_harq->Qm = get_Qm(mcs1); - else if (mcs1<=31) - dlsch0_harq->Qm = (mcs1-28)<<1; - else - LOG_E(PHY,"invalid mcs1 %d\n",mcs1); + 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]; - } else - dlsch0_harq->TBS =0; + // 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; - /* - if (dlsch0_harq->mcs > 18) - printf("mcs %d, TBS %d\n",dlsch0_harq->mcs,dlsch0_harq->TBS); - */ + 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; - if (dlsch1_harq->DCINdi != ndi2) { - dlsch1_harq->round=0; - dlsch1_harq->status = ACTIVE; + 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]; } - dlsch1_harq->DCINdi = ndi2; - dlsch1_harq->mcs = mcs2; - - if (dlsch1_harq->nb_rb>1) { - dlsch1_harq->TBS = TBStable[dlsch1_harq->mcs][dlsch1_harq->nb_rb-1]; - if (mcs2 <= 28) - dlsch1_harq->Qm = get_Qm(mcs2); - else if (mcs1<=31) - dlsch1_harq->Qm = (mcs2-28)<<1; - else - LOG_E(PHY,"invalid mcs2 %d\n",mcs2); - } else - dlsch1_harq->TBS = 0; - - - dlsch0->rnti = rnti; - dlsch1->rnti = rnti; - - dlsch0_harq->dl_power_off = 0; //no power offset - dlsch1_harq->dl_power_off = 0; //no power offset - - dlsch0->active = 1; - dlsch1->active = 1; + 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); + } + } +} - break; +void prepare_dl_decoding_format1C(uint8_t N_RB_DL, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + LTE_DL_FRAME_PARMS *frame_parms, + uint32_t rnti, + uint32_t si_rnti, + uint32_t ra_rnti, + uint32_t p_rnti, + uint32_t frame, + uint8_t subframe, + LTE_DL_UE_HARQ_t *pdlsch0_harq, + LTE_UE_DLSCH_t *pdlsch0) +{ - case format2A: + 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; - switch (frame_parms->N_RB_DL) { + pdlsch0_harq->round = 0; + pdlsch0_harq->first_tx = 1; + pdlsch0_harq->vrb_type = DISTRIBUTED; - 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; - 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; - } 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; - } - } 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; - 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; - } 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; - } - } 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); + if (rnti==si_rnti) { // rule from Section 5.3.1 of 36.321 + if (((frame&1) == 0) && (subframe == 5)) + pdlsch0_harq->rvidx = (((3*((frame>>1)&3))+1)>>1)&3; // SIB1 + else + pdlsch0_harq->rvidx = (((3*(subframe&3))+1)>>1)&3; // other SIBs + } + else if ((rnti==p_rnti) || (rnti==ra_rnti)) { // Section 7.1.7.3 + pdlsch0_harq->rvidx = 0; } - 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; - 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; - } 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; - } - } 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; - 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; - } 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; - } - } 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); - } + pdlsch0_harq->Nl = 1; + pdlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI; + pdlsch0_harq->dl_power_off = 1; //no power offset - break; + pdlsch0_harq->codeword = 0; + pdlsch0_harq->mcs = mcs1; + pdlsch0_harq->TBS = TBStable1C[mcs1]; + pdlsch0_harq->Qm = 2; - 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; - 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; - } 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; - } - } 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; - 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; - } 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; - } - } 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; + pdlsch0->current_harq_pid = harq_pid; + pdlsch0->active = 1; + pdlsch0->rnti = rnti; - 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; - 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; - } 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; - } - } 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; - 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; - } 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; - } - } 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); - } + 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; - } + 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; - if (harq_pid>=8) { - LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid); - return(-1); - } + 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; - // printf("UE: format 2A, rballoc=%x, harq_pid= %d, mcs1=%d,mcs2=%d, rv1=%d, rv2=%d, ndi1=%d, ndi2=%d\n",rballoc, harq_pid, mcs1,mcs2,rv1,rv2,ndi1,ndi2); + 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; - // 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 - if (tbswap == 0) { - dlsch0 = dlsch[0]; - dlsch1 = dlsch[1]; - } else { - dlsch0 = dlsch[1]; - dlsch1 = dlsch[0]; + default: + AssertFatal(0,"Format 1C: Unknown N_RB_DL %d\n",frame_parms->N_RB_DL); + break; } +} - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; - dlsch0->current_harq_pid = harq_pid; - dlsch1->current_harq_pid = harq_pid; - dlsch0->harq_ack[subframe].harq_id = harq_pid; - dlsch1->harq_ack[subframe].harq_id = harq_pid; - - 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]; - 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]; +void compute_precoding_info_2cw(uint8_t tpmi, uint8_t tbswap, uint16_t pmi_alloc, LTE_DL_FRAME_PARMS *frame_parms, LTE_DL_UE_HARQ_t *dlsch0_harq, LTE_DL_UE_HARQ_t *dlsch1_harq) +{ - dlsch0_harq->nb_rb = conv_nprb(rah, - rballoc, - frame_parms->N_RB_DL); +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; + } + break; + default: + break; + } +} + +void compute_precoding_info_1cw(uint8_t tpmi, uint16_t pmi_alloc, LTE_DL_FRAME_PARMS *frame_parms, LTE_DL_UE_HARQ_t *dlsch_harq) +{ - dlsch1_harq->nb_rb = dlsch0_harq->nb_rb; +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); + #ifdef DEBUG_HARQ + printf ("[DCI UE] I am calling from the UE side pmi_alloc_new = %d\n", dlsch0->pmi_alloc); + #endif + break; + case 6: + dlsch_harq->mimo_mode = PUSCH_PRECODING1; + dlsch_harq->pmi_alloc = pmi_alloc;;//pmi_convert(frame_parms,dlsch0->pmi_alloc,1); + #ifdef DEBUG_HARQ + printf ("[DCI UE] I am calling from the UE side pmi_alloc_new = %d\n", dlsch0->pmi_alloc); + #endif + break; + } +} - NPRB = dlsch0_harq->nb_rb; +void compute_precoding_info_format2A(uint8_t tpmi, + uint8_t nb_antenna_ports_eNB, + uint8_t tb0_active, + uint8_t tb1_active, + LTE_DL_UE_HARQ_t *dlsch0_harq, + LTE_DL_UE_HARQ_t *dlsch1_harq) +{ + dlsch0_harq->dl_power_off = 0; + dlsch1_harq->dl_power_off = 0; - if (NPRB==0) { - LOG_E(PHY,"Format 2A: NPRB=0 (rballoc %x,mcs %d, frame_type %d N_RB_DL %d)\n",rballoc,mcs,frame_parms->frame_type,frame_parms->N_RB_DL); - return(-1); - } + 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; - // printf("NPRB %d\n",NPRB); - dlsch0_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; - dlsch1_harq->delta_PUCCH = delta_PUCCH_lut[TPC&3]; + 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; - dlsch0_harq->mcs = mcs1; - dlsch1_harq->mcs = mcs2; + 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; - dlsch0_harq->rvidx = rv1; - dlsch1_harq->rvidx = rv2; + 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; - dlsch0_harq->Nl = 1; - dlsch1_harq->Nl = 1; - // dlsch[0]->layer_index = 0; + case 1: // two-layers on TB 0 + dlsch1_harq->mimo_mode = LARGE_CDD; + dlsch1_harq->Nl = 2; + dlsch0_harq->dl_power_off = 1; + break; - dlsch0_harq->dl_power_off = 1; //no power offset - dlsch1_harq->dl_power_off = 1; //no power offset + 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): Subframe %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,subframe,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); - dlsch0->active = 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; - } +void prepare_dl_decoding_format2_2A(DCI_format_t dci_format, + DCI_INFO_EXTRACTED_t *pdci_info_extarcted, + LTE_DL_FRAME_PARMS *frame_parms, + uint16_t rnti, + uint8_t subframe, + LTE_DL_UE_HARQ_t *dlsch0_harq, + LTE_DL_UE_HARQ_t *dlsch1_harq, + LTE_UE_DLSCH_t *pdlsch0, + LTE_UE_DLSCH_t *pdlsch1) +{ - if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { - dlsch1->active = 0; - } + 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 = 0; + uint8_t TB1_active = 0; - // printf("Format2A DCI (UE, hard pid %d): ndi %d, old_ndi %d (first tx %d)\n",harq_pid,ndi,dlsch0_harq->DCINdi, - // dlsch0_harq->first_tx); - if (dlsch0->active == 1) { - if ((ndi1!=dlsch0_harq->DCINdi)|| - (dlsch0_harq->first_tx==1)) { - // printf("Rate: setting round to zero (ndi %d, DCINdi %d,first_tx %d)\n",ndi,dlsch0_harq->DCINdi,dlsch0_harq->first_tx); - dlsch0_harq->round=0; - dlsch0_harq->status = ACTIVE; - dlsch0_harq->DCINdi = ndi1; - if (dlsch0_harq->first_tx==1) { - LOG_D(PHY,"[PDSCH %x/%d] Format 2A DCI First TX0: Clearing flag\n",rnti,harq_pid); - dlsch0_harq->first_tx = 0; - } - } else if (dlsch0_harq->status == SCH_IDLE) { // we got an Ndi = 0 for a previously decoded process, - // this happens if either another harq process in the same - // is NAK or an ACK was not received + // check if either TB is disabled (see 36-213 V8.6 p. 26) + TB0_active = 1; + TB1_active = 1; - 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; - // printf("Got NDI=0 for correctly decoded SDU (harq_pid %d) subframe %d\n",harq_pid,subframe); + if ((rv1 == 1) && (mcs1 == 0)) { + TB0_active=0; + } + if ((rv2 == 1) && (mcs2 == 0)) { + TB1_active=0; } - } - if (dlsch1->active == 1) { - if ((ndi2!=dlsch1_harq->DCINdi)|| - (dlsch1_harq->first_tx==1)) { - dlsch1_harq->round=0; - dlsch1_harq->status = ACTIVE; - dlsch1_harq->DCINdi = ndi2; +#ifdef DEBUG_HARQ + printf("[DCI UE]: TB0 status %d , TB1 status %d\n", TB0_active, TB1_active); +#endif - if (dlsch1_harq->first_tx==1) { - LOG_D(PHY,"[PDSCH %x/%d] Format 2A DCI First TX1: Clearing flag\n",rnti,harq_pid); - dlsch1_harq->first_tx = 0; - } + 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; - } else if (dlsch1_harq->status == SCH_IDLE) { // we got an Ndi = 0 for a previously decoded process, - // this happens if either another harq process in the same - // is NAK or an ACK was not received + pdlsch0->current_harq_pid = harq_pid; + pdlsch0->harq_ack[subframe].harq_id = harq_pid; + pdlsch1->current_harq_pid = harq_pid; + pdlsch1->harq_ack[subframe].harq_id = harq_pid; - dlsch1->harq_ack[subframe].ack = 1; - dlsch1->harq_ack[subframe].harq_id = harq_pid; - dlsch1->harq_ack[subframe].send_harq_status = 1; - dlsch1->active = 0; - // printf("Got NDI=0 for correctly decoded SDU (harq_pid %d) subframe %d\n",harq_pid,subframe); - } - } + // 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 (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 (TB0_active && TB1_active && tbswap==1) { + dlsch0_harq->codeword = 1; + dlsch1_harq->codeword = 0; + } - - if ((dlsch0->active==1) && (dlsch1->active==1)) { - dlsch0_harq->mimo_mode = LARGE_CDD; - dlsch1_harq->mimo_mode = LARGE_CDD; - dlsch0_harq->dl_power_off = 0; //apply power offset - dlsch1_harq->dl_power_off = 0; //apply power offset - } else { - dlsch0_harq->mimo_mode = ALAMOUTI; - dlsch1_harq->mimo_mode = ALAMOUTI; + 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 } - } 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->dl_power_off = 0; //apply power offset - dlsch1_harq->dl_power_off = 0; //apply power offset - 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]; - break; + if (TB1_active==0) { + dlsch1_harq->status = SCH_IDLE; + pdlsch1->active = 0; + } - case 1: // one-layers on TB 0, two on TB 1 - dlsch0_harq->mimo_mode = LARGE_CDD; - dlsch1_harq->mimo_mode = LARGE_CDD; - dlsch0_harq->dl_power_off = 0; //apply power offset - dlsch1_harq->dl_power_off = 0; //apply power offset - dlsch1_harq->Nl = 2; - dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][(dlsch1_harq->nb_rb<<1)-1]; - break; +//#ifdef DEBUG_HARQ + printf("[DCI UE]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); +//#endif - 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 = 0; //apply power offset - dlsch1_harq->dl_power_off = 0; //apply power offset + // compute resource allocation + if (TB0_active == 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"); - } + 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); - break; + 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]; - case 3: // - LOG_E(PHY,"Illegal value (3) for TPMI in Format 2A DCI\n"); - break; + 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); } - } 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->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; + // 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); + } 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, pdlsch0->pmi_alloc, frame_parms, dlsch1_harq); + } + //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); + } + + // reset round + compute Qm + if (TB0_active) { + if ((ndi1!=dlsch0_harq->DCINdi) || (dlsch0_harq->first_tx==1)) { + dlsch0_harq->round = 0; + + //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(dlsch0_harq->round == 0) { +#if 0 + // 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; +#endif + } } - } 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; - dlsch0_harq->dl_power_off = 1; //apply power offset - dlsch1_harq->dl_power_off = 0; //apply power offset - dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][(dlsch1_harq->nb_rb<<1)-1]; - break; + // 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 subframe %d (pid %d, round %d) TBS %d \n", + subframe,harq_pid,dlsch0_harq->round, dlsch0_harq->TBS); + } + else + { + LOG_D(PHY,"[UE] DLSCH: Keep the same TBS CW0 subframe %d (pid %d, round %d) TBS %d \n", + subframe,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; + } + + if (TB1_active) { + if ((ndi2!=dlsch1_harq->DCINdi) || (dlsch1_harq->first_tx==1)) { + dlsch1_harq->round = 0; + //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 0 + if(dlsch1_harq->round == 0) { + // 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; + } +#endif + } - 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; + // 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 subframe %d (pid %d, round %d) TBS %d \n", + subframe,harq_pid,dlsch1_harq->round, dlsch1_harq->TBS); } - } - } else { - LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antenna_ports_eNB); + else + { + LOG_D(PHY,"[UE] DLSCH: Keep the same TBS CW1 subframe %d (pid %d, round %d) TBS %d \n", + subframe,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; + } + +//#ifdef DEBUG_HARQ + printf("[DCI UE]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); +//#endif + + #ifdef DEBUG_HARQ + 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 +} + +int generate_ue_dlsch_params_from_dci(int frame, + uint8_t subframe, + void *dci_pdu, + uint16_t rnti, + DCI_format_t dci_format, + LTE_UE_DLSCH_t **dlsch, + LTE_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; + LTE_UE_DLSCH_t *dlsch0=NULL,*dlsch1=NULL; + LTE_DL_UE_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL; + DCI_INFO_EXTRACTED_t dci_info_extarcted; + uint8_t status=0; + + 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, + subframe, + (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, subframe); +#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, subframe); +#endif + status = check_dci_format1_1a_coherency(format1A, + frame_parms->N_RB_DL, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti,frame,subframe, + &dci_info_extarcted, + dlsch0_harq); + if(status == 0) + 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, subframe); +#endif + prepare_dl_decoding_format1_1A(format1A, + frame_parms->N_RB_DL, + &dci_info_extarcted, + frame_parms, + subframe, + 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); - if (mcs1 <= 28) - dlsch0_harq->Qm = get_Qm(mcs1); - else if (mcs1<=31) - dlsch0_harq->Qm = (mcs1-28)<<1; - else - LOG_E(PHY,"invalid mcs1 %d\n",mcs1); - - if (mcs2 <= 28) - dlsch1_harq->Qm = get_Qm(mcs2); - else if (mcs2<=31) - dlsch1_harq->Qm = (mcs2-28)<<1; - else - LOG_E(PHY,"invalid mcs2 %d\n",mcs2); - - // 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): Subframe %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,subframe,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); + // 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, + rnti, + si_rnti, + ra_rnti, + p_rnti, + frame, + subframe, + dlsch0_harq, + dlsch0); + break; + } - break; + case format1: + { + // extract dci infomation +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1] AbsSubframe %d.%d extarct dci info \n", frame, subframe); +#endif + extract_dci1_info(frame_parms->N_RB_DL, + frame_type, + dci_pdu, + &dci_info_extarcted); - case format1E_2A_M10PRB: + // check dci content + dlsch0 = dlsch[0]; + dlsch0->active = 0; + dlsch0_harq = dlsch[0]->harq_processes[dci_info_extarcted.harq_pid]; - harq_pid = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->harq_pid; +#ifdef DEBUG_DCI + LOG_I(PHY,"[DCI-FORMAT-1] AbsSubframe %d.%d check dci coherency \n", frame, subframe); +#endif + status = check_dci_format1_1a_coherency(format1, + frame_parms->N_RB_DL, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti,frame,subframe, + &dci_info_extarcted, + dlsch0_harq); + if(status == 0) + return(-1); - if (harq_pid>=8) { - LOG_E(PHY,"Format 1E_2A_M10PRB: harq_pid=%d >= 8\n", harq_pid); - 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, subframe); +#endif + prepare_dl_decoding_format1_1A(format1, + frame_parms->N_RB_DL, + &dci_info_extarcted, + frame_parms, + subframe, + rnti, + tc_rnti, + si_rnti, + ra_rnti, + p_rnti, + dlsch0_harq, + dlsch0); + break; } - dlsch[0]->current_harq_pid = harq_pid; - dlsch[0]->harq_ack[subframe].harq_id = harq_pid; + 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 = 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]; + } - /* - tbswap = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tb_swap; - if (tbswap == 0) { + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + + //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, + rnti, + subframe, + 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, subframe); + 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{ + } 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, + rnti, + subframe, + 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); } - */ - dlsch0 = dlsch[0]; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - 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; + dlsch[0]->current_harq_pid = harq_pid; + dlsch[0]->harq_ack[subframe].harq_id = harq_pid; - 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]; + /* + 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->mcs>20) { + printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); + return(-1); + } + */ - if ((dlsch0_harq->rvidx == 1) && (dlsch0_harq->mcs == 0)) { - dlsch0_harq->status = DISABLED; - } + //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; - //if ((dlsch1_harq->rvidx == 1) && (dlsch1_harq->mcs == 0)) { - //dlsch1_harq->status = DISABLED; - //} - dlsch0_harq->Nl = 1; + // check if either TB is disabled (see 36-213 V8.6 p. 26) - //dlsch0->layer_index = tbswap; - //dlsch1->layer_index = 1-tbswap; + 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; - // Fix this - tpmi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tpmi; - // printf("ue: tpmi %d\n",tpmi); + //dlsch0->layer_index = tbswap; + //dlsch1->layer_index = 1-tbswap; - 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); - break; + // Fix this + tpmi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tpmi; + // printf("ue: tpmi %d\n",tpmi); - case 2: - dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1); - break; + switch (tpmi) { + case 0 : + dlsch0_harq->mimo_mode = ALAMOUTI; + break; - case 3: - dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2); - break; + case 1: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING11; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,0,0); + break; - case 4: - dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj; - dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3); - break; + case 2: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1m1; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,1, 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 3: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1j; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,2, 0); - case 6: - dlsch0_harq->mimo_mode = PUSCH_PRECODING1; - LOG_E(PHY,"Unsupported TPMI\n"); - return(-1); - break; - } + break; + case 4: + dlsch0_harq->mimo_mode = UNIFORM_PRECODING1mj; + dlsch0_harq->pmi_alloc = pmi_extend(frame_parms,3, 0); + break; - if (frame_parms->mode1_flag == 1) - dlsch0_harq->mimo_mode = SISO; + 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 (dlsch0_harq->DCINdi != ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi) { - dlsch0_harq->round = 0; - dlsch0_harq->status = ACTIVE; - } else if (dlsch0_harq->status == SCH_IDLE) { // we got an Ndi = 0 for a previously decoded process, - // this happens if either another harq process in the same - // is NAK or an ACK was not received + if (frame_parms->mode1_flag == 1) + dlsch0_harq->mimo_mode = SISO; - 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->DCINdi != ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi) { - 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_harq->round = 0; + dlsch0_harq->status = ACTIVE; + } else if (dlsch0_harq->status == SCH_IDLE) { // we got an Ndi = 0 for a previously decoded process, + // this happens if either another harq process in the same + // is NAK or an ACK was not received - dlsch0->rnti = rnti; - //dlsch1->rnti = rnti; + 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->active = 1; - //dlsch1->active = 1; + dlsch0_harq->DCINdi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->ndi; + dlsch0_harq->mcs = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->mcs; - 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; + 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; - break; + dlsch0->active = 1; + //dlsch1->active = 1; - default: - LOG_E(PHY,"format %d not yet implemented\n",dci_format); - return(-1); - break; - } + 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; -#ifdef DEBUG_DCI + break; - if (dlsch[0] && (dlsch[0]->rnti != 0xffff)) { - printf("dci_format:%d Abssubframe: %d.%d \n",dci_format,frame%1024,subframe); - printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); - printf("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); - printf("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc_even[0]); - printf("PDSCH dlsch0 UE: harq_pid %d\n",harq_pid); - printf("PDSCH dlsch0 UE: tpc %d\n",TPC); - printf("PDSCH dlsch0 UE: g %d\n",dlsch[0]->g_pucch); - printf("PDSCH dlsch0 UE: round %d\n",dlsch0_harq->round); - printf("PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); - printf("PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); - printf("PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); - printf("PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); - printf("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); - } + default: + LOG_E(PHY,"format %d not yet implemented\n",dci_format); + return(-1); + break; + } -#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(subframe), 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)); - } + +#ifdef DEBUG_DCI + + if (dlsch[0] && (dlsch[0]->rnti != 0xffff)) { + printf("dci_format:%d Abssubframe: %d.%d \n",dci_format,frame%1024,subframe); + printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); + printf("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); + printf("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc_even[0]); + printf("PDSCH dlsch0 UE: harq_pid %d\n",harq_pid); + //printf("PDSCH dlsch0 UE: tpc %d\n",TPC); + printf("PDSCH dlsch0 UE: g %d\n",dlsch[0]->g_pucch); + printf("PDSCH dlsch0 UE: round %d\n",dlsch0_harq->round); + printf("PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); + printf("PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); + printf("PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); + printf("PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); + printf("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); + } #endif - // compute DL power control parameters - computeRhoA_UE(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off); + #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(subframe), 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 - computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off); - return(0); + // 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); } @@ -5818,14 +6593,79 @@ uint32_t pdcch_alloc2ul_frame(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, ui } -uint16_t quantize_subband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,int nb_subbands) +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; - uint16_t pmivect = 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; @@ -5852,13 +6692,37 @@ uint16_t quantize_subband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,int nb_subba // printf("subband %d, pmi%d \n",i,pmiq); pmivect |= (pmiq<<(2*i)); - } else { - // This needs to be done properly!!! - printf("PMI feedback for rank>1 not supported!\n"); + } + + 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); } @@ -6296,14 +7160,32 @@ void reset_cba_uci(void *o) ((HLC_subband_cqi_mcs_CBA_5MHz *)o)->crnti = 0x0; } -uint32_t pmi_extend(LTE_DL_FRAME_PARMS *frame_parms,uint8_t wideband_pmi) + +uint32_t pmi_extend(LTE_DL_FRAME_PARMS *frame_parms,uint8_t wideband_pmi, uint8_t rank) { - uint8_t i,wideband_pmi2=wideband_pmi&3; + uint8_t i,wideband_pmi2; uint32_t pmi_ex = 0; - for (i=0; i<14; i+=2) - pmi_ex|=(wideband_pmi2<<i); + 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); } @@ -6314,7 +7196,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, uint8_t subframe, DCI_format_t dci_format, PHY_VARS_UE *ue, - UE_rxtx_proc_t *proc, + UE_rxtx_proc_t *proc, uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, @@ -6327,7 +7209,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, uint8_t transmission_mode = ue->transmission_mode[eNB_id]; ANFBmode_t AckNackFBMode; LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; - LTE_UE_DLSCH_t **dlsch = ue->dlsch[0]; + LTE_UE_DLSCH_t **dlsch = ue->dlsch[subframe&0x1][0]; PHY_MEASUREMENTS *meas = &ue->measurements; LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; // uint32_t current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id]; @@ -7128,15 +8010,23 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, 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_subframe = (subframe<4) ? (subframe+6) : (subframe-4); + int dl_subframe = subframe; - if (ue->dlsch[eNB_id][0]->harq_ack[dl_subframe].send_harq_status>0) { // we have downlink transmission + if (ue->dlsch[dl_subframe&0x1][eNB_id][0]->harq_ack[dl_subframe].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; @@ -7148,10 +8038,16 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, dlsch[0]->harq_ack[subframe].vDAI_UL = dai+1; - LOG_D(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\n", + + /*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); + 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; @@ -7159,7 +8055,6 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->Nsymb_pusch = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1); ulsch->srs_active = use_srs; - ulsch->bundling = 1-AckNackFBMode; if ((rnti >= cba_rnti) && (rnti < p_rnti)) ulsch->harq_processes[harq_pid]->status = CBA_ACTIVE; @@ -7204,7 +8099,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; - #ifdef DEBUG_DCI +#ifdef DEBUG_DCI + printf("Format 0 DCI : ulsch (ue): AbsSubframe %d.%d\n",proc->frame_rx%1024,subframe); printf("Format 0 DCI : ulsch (ue): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); printf("Format 0 DCI :ulsch (ue): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); @@ -7238,8 +8134,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, } int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, - eNB_rxtx_proc_t *proc, - void *dci_pdu, + eNB_rxtx_proc_t *proc, + void *dci_pdu, uint16_t rnti, DCI_format_t dci_format, uint8_t UE_id, @@ -7277,11 +8173,9 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, harq_pid = subframe2harq_pid(frame_parms, pdcch_alloc2ul_frame(frame_parms, - proc->frame_tx, - subframe), + proc->frame_tx, + subframe), pdcch_alloc2ul_subframe(frame_parms,subframe)); - - switch (frame_parms->N_RB_DL) { case 6: if (frame_parms->frame_type == TDD) { @@ -7763,6 +8657,8 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, 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); @@ -7786,7 +8682,6 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, 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; - ulsch->bundling = 1-AckNackFBMode; //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1) if(cshift == 0) diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index 8e17697ff48896aa21c1404128046a95f6167cbd..dced65fa2cbe84432a11a6bf5611ae36da28068c 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -79,11 +79,17 @@ #if !defined(C_RNTI) #define C_RNTI (rnti_t)0x1234 #endif - -#define PMI_2A_11 0 +// These are the codebook indexes according to Table 6.3.4.2.3-1 of 36.211 +//1 layer +#define PMI_2A_11 0 #define PMI_2A_1m1 1 -#define PMI_2A_1j 2 +#define PMI_2A_1j 2 #define PMI_2A_1mj 3 +//2 layers +#define PMI_2A_R1_10 0 +#define PMI_2A_R1_11 1 +#define PMI_2A_R1_1j 2 + typedef enum { SCH_IDLE, @@ -158,6 +164,8 @@ typedef struct { uint8_t Nlayers; /// First layer for this PSCH transmission uint8_t first_layer; + /// codeword this transport block is mapped to + uint8_t codeword; } LTE_DL_eNB_HARQ_t; typedef struct { @@ -584,6 +592,8 @@ typedef struct { uint32_t trials[8]; /// error statistics per round uint32_t errors[8]; + /// codeword this transport block is mapped to + uint8_t codeword; } LTE_DL_UE_HARQ_t; typedef struct { @@ -698,7 +708,7 @@ typedef struct { int16_t sqrt_rho_a; /// amplitude of PDSCH (compared to RS) in symbols containing pilots int16_t sqrt_rho_b; - /// Current HARQ process id + /// Current HARQ process id threadRx Odd and threadRx Even uint8_t current_harq_pid; /// Current subband antenna selection uint32_t antenna_alloc; @@ -754,13 +764,21 @@ typedef enum { PMCH } PDSCH_t; +typedef enum { + rx_standard=0, + rx_IC_single_stream, + rx_IC_dual_stream, + rx_SIC_dual_stream +} RX_type_t; + typedef enum { pucch_format1=0, pucch_format1a, pucch_format1b, pucch_format2, pucch_format2a, - pucch_format2b + pucch_format2b, + pucch_format3 // PUCCH format3 } PUCCH_FMT_t; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 8ec2a40d8de12b481fd90ad783595698de551dcb..90f8242cc87c9af6a507b0b0850114c125189a3e 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -40,6 +40,8 @@ #include "SCHED/defs.h" #include "defs.h" #include "UTIL/LOG/vcd_signal_dumper.h" +#include "UTIL/LOG/log.h" +#include <syscall.h> //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 @@ -85,11 +87,11 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) #endif for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++) { - + #ifdef DEBUG_DLSCH_FREE printf("Freeing dlsch process %d c[%d] (%p)\n",i,r,dlsch->harq_processes[i]->c[r]); #endif - + if (dlsch->harq_processes[i]->c[r]) { free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); dlsch->harq_processes[i]->c[r] = NULL; @@ -98,17 +100,17 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); dlsch->harq_processes[i]->d[r] = NULL; } - + } free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t)); dlsch->harq_processes[i] = NULL; } } - + free16(dlsch,sizeof(LTE_eNB_DLSCH_t)); dlsch = NULL; } - + } LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms) @@ -148,7 +150,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ for (layer=0; layer<4; layer++) { dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) { @@ -160,7 +162,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - + } for (i=0; i<10; i++) @@ -207,7 +209,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ exit_flag=3; } } - + if (exit_flag==0) { for (i=0; i<Mdlharq; i++) { dlsch->harq_processes[i]->round=0; @@ -218,7 +220,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ if (dlsch->harq_processes[i]->d[r]) dlsch->harq_processes[i]->d[r][j] = LTE_NULL; } - + } return(dlsch); @@ -257,7 +259,7 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++) if (dlsch->harq_processes[i]->d[r]) dlsch->harq_processes[i]->d[r][j] = LTE_NULL; - + } } } @@ -347,12 +349,14 @@ int dlsch_encoding_2threads0(te_params *tep) { extern int oai_exit; void *te_thread(void *param) { + pthread_setname_np( pthread_self(),"te processing"); + LOG_I(PHY,"thread te created id=%ld", syscall(__NR_gettid)); eNB_proc_t *proc = &((te_params *)param)->eNB->proc; while (!oai_exit) { - if (wait_on_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread")<0) break; + if (wait_on_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread")<0) break; dlsch_encoding_2threads0((te_params*)param); @@ -432,14 +436,14 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, return(-1); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); ++proc->instance_cnt_te; proc->tep.eNB = eNB; proc->tep.dlsch = dlsch; proc->tep.G = G; - // wakeup worker to do second half segments + // wakeup worker to do second half segments if (pthread_cond_signal(&proc->cond_te) != 0) { printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); exit_fun( "ERROR pthread_cond_signal" ); @@ -497,8 +501,8 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, proc->tep.eNB = eNB; proc->tep.dlsch = dlsch; proc->tep.G = G; - - // wakeup worker to do second half segments + + // wakeup worker to do second half segments if (pthread_cond_signal(&proc->cond_te) != 0) { printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); exit_fun( "ERROR pthread_cond_signal" ); @@ -545,9 +549,9 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, // wait for worker to finish - wait_on_busy_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread"); + wait_on_busy_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread"); + - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); @@ -729,6 +733,186 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, return(0); } + +int dlsch_encoding_SIC(PHY_VARS_UE *ue, + unsigned char *a, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe, + time_stats_t *rm_stats, + time_stats_t *te_stats, + time_stats_t *i_stats) +{ + + unsigned int G; + unsigned int crc=1; + unsigned short iind; + + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + unsigned char harq_pid = dlsch->current_harq_pid; + unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; + unsigned int A; + unsigned char mod_order; + unsigned int Kr=0,Kr_bytes,r,r_offset=0; + unsigned short m=dlsch->harq_processes[harq_pid]->mcs; + uint8_t beamforming_mode=0; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); + + A = dlsch->harq_processes[harq_pid]->TBS; //6228 + // printf("Encoder: A: %d\n",A); + mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs); + + if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7) + beamforming_mode = 7; + else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8) + beamforming_mode = 8; + else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10) + beamforming_mode = 9; + G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode); + + + // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet + if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet + + /* + int i; + printf("dlsch (tx): \n"); + for (i=0;i<(A>>3);i++) + printf("%02x.",a[i]); + printf("\n"); + */ + // Add 24-bit crc (polynomial A) to payload + crc = crc24a(a, + A)>>8; + a[A>>3] = ((uint8_t*)&crc)[2]; + a[1+(A>>3)] = ((uint8_t*)&crc)[1]; + a[2+(A>>3)] = ((uint8_t*)&crc)[0]; + // printf("CRC %x (A %d)\n",crc,A); + + dlsch->harq_processes[harq_pid]->B = A+24; + // dlsch->harq_processes[harq_pid]->b = a; + memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); + + if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, + dlsch->harq_processes[harq_pid]->c, + dlsch->harq_processes[harq_pid]->B, + &dlsch->harq_processes[harq_pid]->C, + &dlsch->harq_processes[harq_pid]->Cplus, + &dlsch->harq_processes[harq_pid]->Cminus, + &dlsch->harq_processes[harq_pid]->Kplus, + &dlsch->harq_processes[harq_pid]->Kminus, + &dlsch->harq_processes[harq_pid]->F)<0) + return(-1); + + for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) { + + if (r<dlsch->harq_processes[harq_pid]->Cminus) + Kr = dlsch->harq_processes[harq_pid]->Kminus; + else + Kr = dlsch->harq_processes[harq_pid]->Kplus; + + Kr_bytes = Kr>>3; + + // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14) + if (Kr_bytes<=64) + iind = (Kr_bytes-5); + else if (Kr_bytes <=128) + iind = 59 + ((Kr_bytes-64)>>1); + else if (Kr_bytes <= 256) + iind = 91 + ((Kr_bytes-128)>>2); + else if (Kr_bytes <= 768) + iind = 123 + ((Kr_bytes-256)>>3); + else { + printf("dlsch_coding: Illegal codeword size %d!!!\n",Kr_bytes); + return(-1); + } + + +#ifdef DEBUG_DLSCH_CODING + printf("Generating Code Segment %d (%d bits)\n",r,Kr); + // generate codewords + + printf("bits_per_codeword (Kr)= %d, A %d\n",Kr,A); + printf("N_RB = %d\n",nb_rb); + printf("Ncp %d\n",frame_parms->Ncp); + printf("mod_order %d\n",mod_order); +#endif + + +#ifdef DEBUG_DLSCH_CODING + printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]); +#endif + start_meas(te_stats); + threegpplte_turbo_encoder(dlsch->harq_processes[harq_pid]->c[r], + Kr>>3, + &dlsch->harq_processes[harq_pid]->d[r][96], + (r==0) ? dlsch->harq_processes[harq_pid]->F : 0, + f1f2mat_old[iind*2], // f1 (see 36121-820, page 14) + f1f2mat_old[(iind*2)+1] // f2 (see 36121-820, page 14) + ); + stop_meas(te_stats); +#ifdef DEBUG_DLSCH_CODING + + if (r==0) + write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); + +#endif + start_meas(i_stats); + dlsch->harq_processes[harq_pid]->RTC[r] = + sub_block_interleaving_turbo(4+(Kr_bytes*8), + &dlsch->harq_processes[harq_pid]->d[r][96], + dlsch->harq_processes[harq_pid]->w[r]); + stop_meas(i_stats); + } + + } + + // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the + // outputs for each code segment, see Section 5.1.5 p.20 + + for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) { +#ifdef DEBUG_DLSCH_CODING + printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", + r, + G, + Kr*3, + mod_order,nb_rb); +#endif + + start_meas(rm_stats); + r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], + G, //G + dlsch->harq_processes[harq_pid]->w[r], + dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->C, // C + dlsch->Nsoft, // Nsoft, + dlsch->Mdlharq, + dlsch->Kmimo, + dlsch->harq_processes[harq_pid]->rvidx, + get_Qm(dlsch->harq_processes[harq_pid]->mcs), + dlsch->harq_processes[harq_pid]->Nl, + r, + nb_rb, + m); // r + stop_meas(rm_stats); +#ifdef DEBUG_DLSCH_CODING + + if (r==dlsch->harq_processes[harq_pid]->C-1) + write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4); + +#endif + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); + + return(0); +} + + + + #ifdef PHY_ABSTRACTION void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB, uint8_t *DLSCH_pdu, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c index 9629502cecd0300a6fc00f7c284d10d9fd484c00..05f458e94a2e05b49172e1d8b5351181faaa7888 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c @@ -37,7 +37,8 @@ #include "SCHED/extern.h" #include "SIMULATION/TOOLS/defs.h" //#define DEBUG_DLSCH_DECODING - + +extern double cpuf; void free_ue_dlsch(LTE_UE_DLSCH_t *dlsch) { @@ -159,7 +160,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_DLSCH_t *dlsch, LTE_DL_UE_HARQ_t *harq_process, - uint8_t frame, + uint32_t frame, uint8_t subframe, uint8_t harq_pid, uint8_t is_crnti, @@ -270,7 +271,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, return(max_turbo_iterations); }*/ - /*harq_pid = dlsch->current_harq_pid; + /*harq_pid = dlsch->current_harq_pid[subframe&0x1]; if (harq_pid >= 8) { printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid); return(max_turbo_iterations); @@ -341,9 +342,11 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, printf("Segmentation: C %d, Cminus %d, Kminus %d, Kplus %d\n",harq_process->C,harq_process->Cminus,harq_process->Kminus,harq_process->Kplus); #endif + opp_enabled=1; + for (r=0; r<harq_process->C; r++) { - + // Get Turbo interleaver parameters if (r<harq_process->Cminus) Kr = harq_process->Kminus; @@ -376,7 +379,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, (r==0) ? harq_process->F : 0); #ifdef DEBUG_DLSCH_DECODING - LOG_I(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", + LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", harq_pid,r, G, Kr*3, harq_process->TBS, @@ -387,7 +390,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, harq_process->round); #endif - +//printf("dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); if (lte_rate_matching_turbo_rx(harq_process->RTC[r], G, harq_process->w[r], @@ -458,13 +461,18 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, //#ifndef __AVX2__ #if 1 if (err_flag == 0) { - +/* + LOG_I(PHY, "turbo algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", + Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, + harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_turbo_iterations); +*/ if (llr8_flag) { AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); } start_meas(dlsch_turbo_decoding_stats); + LOG_D(PHY,"AbsSubframe %d.%d Start turbo segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); ret = tc (&harq_process->d[r][96], harq_process->c[r], @@ -486,7 +494,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, stop_meas(dlsch_turbo_decoding_stats); } #else - if ((harq_process->C == 1) || + if ((harq_process->C == 1) || ((r==harq_process->C-1) && (skipped_last==0))) { // last segment with odd number of segments start_meas(dlsch_turbo_decoding_stats); @@ -518,7 +526,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, } else { skipped_last=0; - + if (Kr_last == Kr) { // decode 2 code segments with AVX2 version #ifdef DEBUG_DLSCH_DECODING printf("single decoding segment %d (%p)\n",r-1,&harq_process->d[r-1][96]); @@ -565,7 +573,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, exit(-1);*/ stop_meas(dlsch_turbo_decoding_stats); - } + } else { // Kr_last != Kr start_meas(dlsch_turbo_decoding_stats); ret = tc @@ -585,7 +593,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, &phy_vars_ue->dlsch_tc_intl1_stats, &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1); stop_meas(dlsch_turbo_decoding_stats); - + start_meas(dlsch_turbo_decoding_stats); ret = tc (&harq_process->d[r][96], @@ -604,7 +612,14 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, &phy_vars_ue->dlsch_tc_intl1_stats, &phy_vars_ue->dlsch_tc_intl2_stats); //(is_crnti==0)?harq_pid:harq_pid+1); stop_meas(dlsch_turbo_decoding_stats); - + + /*printf("Segmentation: C %d r %d, dlsch_rate_unmatching_stats %5.3f dlsch_deinterleaving_stats %5.3f dlsch_turbo_decoding_stats %5.3f \n", + harq_process->C, + r, + dlsch_rate_unmatching_stats->p_time/(cpuf*1000.0), + dlsch_deinterleaving_stats->p_time/(cpuf*1000.0), + dlsch_turbo_decoding_stats->p_time/(cpuf*1000.0));*/ + } } } @@ -612,7 +627,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, if ((err_flag == 0) && (ret>=(1+dlsch->max_turbo_iterations))) {// a Code segment is in error so break; - //printf("CRC failed, segment %d\n",r); + LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); err_flag = 1; } } @@ -626,8 +641,8 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, frame_rx_prev = frame_rx_prev%1024; if (err_flag == 1) { - LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, round %d, subframe %d)\n", - phy_vars_ue->Mod_id, frame_rx_prev, subframe_rx_prev, harq_pid, harq_process->round, subframe); + //LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", + // phy_vars_ue->Mod_id, frame, subframe, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); dlsch->harq_ack[subframe].ack = 0; dlsch->harq_ack[subframe].harq_id = harq_pid; @@ -636,25 +651,31 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, harq_process->round++; - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round,harq_process->TBS); - } // printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); if (harq_process->round >= dlsch->Mdlharq) { harq_process->status = SCH_IDLE; + harq_process->round = 0; + } + if(is_crnti) + { + LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS); } return((1+dlsch->max_turbo_iterations)); } else { - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, round %d, subframe %d)\n", - phy_vars_ue->Mod_id, frame_rx_prev, subframe_rx_prev, harq_pid, harq_process->round, subframe); + + //LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d TBS %d harq_process->mcs %d harq_process->nb_rb %d\n", + //phy_vars_ue->Mod_id,subframe,harq_process->TBS,harq_process->mcs,harq_process->nb_rb); harq_process->status = SCH_IDLE; harq_process->round = 0; dlsch->harq_ack[subframe].ack = 1; dlsch->harq_ack[subframe].harq_id = harq_pid; dlsch->harq_ack[subframe].send_harq_status = 1; + //LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", + // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); + if(is_crnti) { LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round,harq_process->TBS); @@ -747,7 +768,7 @@ int dlsch_abstraction_EESM(double* sinr_dB, uint8_t TM, uint32_t rb_alloc[4], ui bler = interp(sinr_eff,&sinr_bler_map[mcs][0][0],&sinr_bler_map[mcs][1][0],table_length[mcs]); -#ifdef USER_MODE // need to be adapted for the emulation in the kernel space +#ifdef USER_MODE // need to be adapted for the emulation in the kernel space if (uniformrandom() < bler) { LOG_I(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f, TM %d)\n",mcs,sinr_eff,bler, TM); @@ -830,7 +851,7 @@ int dlsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint32_t rb_alloc[4], ui bler = interp(sinr_eff,&sinr_bler_map[mcs][0][0],&sinr_bler_map[mcs][1][0],table_length[mcs]); -#ifdef USER_MODE // need to be adapted for the emulation in the kernel space +#ifdef USER_MODE // need to be adapted for the emulation in the kernel space if (uniformrandom() < bler) { LOG_N(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); @@ -908,9 +929,9 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, break; case PDSCH: // TB0 - dlsch_ue = phy_vars_ue->dlsch[eNB_id][0]; + dlsch_ue = phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]; harq_pid = dlsch_ue->current_harq_pid; - ue_id= (uint32_t)find_ue((int16_t)phy_vars_ue->pdcch_vars[(uint32_t)eNB_id]->crnti,PHY_vars_eNB_g[eNB_id2][CC_id]); + ue_id= (uint32_t)find_ue((int16_t)phy_vars_ue->pdcch_vars[subframe & 0x1][(uint32_t)eNB_id]->crnti,PHY_vars_eNB_g[eNB_id2][CC_id]); DevAssert( ue_id != (uint32_t)-1 ); dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch[ue_id][0]; @@ -954,9 +975,9 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, break; case PDSCH1: { // TB1 - dlsch_ue = phy_vars_ue->dlsch[eNB_id][1]; + dlsch_ue = phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]; harq_pid = dlsch_ue->current_harq_pid; - int8_t UE_id = find_ue( phy_vars_ue->pdcch_vars[eNB_id]->crnti, PHY_vars_eNB_g[eNB_id2][CC_id] ); + int8_t UE_id = find_ue( phy_vars_ue->pdcch_vars[subframe & 0x1][eNB_id]->crnti, PHY_vars_eNB_g[eNB_id2][CC_id] ); DevAssert( UE_id != -1 ); dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch[UE_id][1]; // reset HARQ @@ -1008,7 +1029,7 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, break; default: - dlsch_ue = phy_vars_ue->dlsch[eNB_id][0]; + dlsch_ue = phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]; LOG_E(PHY,"dlsch_decoding_emul: FATAL, unknown DLSCH_id %d\n",dlsch_id); dlsch_ue->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; return(1+dlsch_ue->max_turbo_iterations); diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c index 7d14e8aca716942346e5c6b1d930321aee1e0221..1450209c260a6d7abb8fa1904df9afe42cf8d7a7 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c @@ -29,9 +29,9 @@ * \note * \warning */ - -#include "PHY/defs.h" +//#include "PHY/defs.h" #include "PHY/extern.h" +#include "SCHED/defs.h" #include "defs.h" #include "extern.h" #include "PHY/sse_intrin.h" @@ -43,13 +43,33 @@ #define NOCYGWIN_STATIC #endif +/* dynamic shift for LLR computation for TM3/4 + * set as command line argument, see lte-softmodem.c + * default value: 0 + */ +int16_t dlsch_demod_shift = 0; + +//#define DEBUG_HARQ + +//#undef LOG_D +//#define LOG_D LOG_I + //#define DEBUG_PHY 1 //#define DEBUG_DLSCH_DEMOD 1 -int avg[4]; + // [MCS][i_mod (0,1,2) = (2,4,6)] unsigned char offset_mumimo_llr_drange_fix=0; +uint8_t interf_unaw_shift0=0; +uint8_t interf_unaw_shift1=0; +uint8_t interf_unaw_shift=0; +//inferference-free case +unsigned char interf_unaw_shift_tm4_mcs[29]={5, 3, 4, 3, 3, 2, 1, 1, 2, 0, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 0, 2, 1, 0, 1, 0, 1, 0, 0} ; +unsigned char interf_unaw_shift_tm1_mcs[29]={5, 5, 4, 3, 3, 3, 2, 2, 4, 4, 2, 3, 3, 3, 1, 1, + 0, 1, 1, 2, 5, 4, 4, 6, 5, 1, 0, 5, 6} ; // mcs 21, 26, 28 seem to be errorneous + /* //original values from sebastion + same hand tuning unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{6,6,6},{6,6,6},{6,6,6},{5,5,5},{4,4,4},{1,2,4}, // QPSK @@ -78,7 +98,7 @@ int rx_pdsch(PHY_VARS_UE *ue, uint8_t subframe, unsigned char symbol, unsigned char first_symbol_flag, - unsigned char dual_stream_flag, + RX_type_t rx_type, unsigned char i_mod, unsigned char harq_pid) { @@ -86,37 +106,77 @@ int rx_pdsch(PHY_VARS_UE *ue, LTE_UE_COMMON *common_vars = &ue->common_vars; LTE_UE_PDSCH **pdsch_vars; LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - PHY_MEASUREMENTS *phy_measurements = &ue->measurements; + PHY_MEASUREMENTS *measurements = &ue->measurements; LTE_UE_DLSCH_t **dlsch; + int avg[4]; + int avg_0[2]; + int avg_1[2]; + unsigned char aatx,aarx; - unsigned short nb_rb=0; + + unsigned short nb_rb = 0, round; int avgs, rb; LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0; - + uint8_t beamforming_mode; uint32_t *rballoc; + int32_t **rxdataF_comp_ptr; + int32_t **dl_ch_mag_ptr; + int32_t codeword_TB0 = -1; + int32_t codeword_TB1 = -1; + + + switch (type) { case SI_PDSCH: pdsch_vars = &ue->pdsch_vars_SI[eNB_id]; - dlsch = &ue->dlsch_SI[eNB_id]; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch = &ue->dlsch_SI[eNB_id]; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; beamforming_mode = 0; break; case RA_PDSCH: pdsch_vars = &ue->pdsch_vars_ra[eNB_id]; - dlsch = &ue->dlsch_ra[eNB_id]; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch = &ue->dlsch_ra[eNB_id]; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; beamforming_mode = 0; break; case PDSCH: - pdsch_vars = &ue->pdsch_vars[subframe&0x1][eNB_id]; - dlsch = ue->dlsch[eNB_id]; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; + pdsch_vars = ue->pdsch_vars[subframe&0x1]; + dlsch = ue->dlsch[subframe&0x1][eNB_id]; + LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", + frame,subframe,symbol,harq_pid, + dlsch[0]->harq_processes[harq_pid]->status, + dlsch[1]->harq_processes[harq_pid]->status); + + if ((dlsch[0]->harq_processes[harq_pid]->status == ACTIVE) && + (dlsch[1]->harq_processes[harq_pid]->status == ACTIVE)){ + codeword_TB0 = dlsch[0]->harq_processes[harq_pid]->codeword; + codeword_TB1 = dlsch[1]->harq_processes[harq_pid]->codeword; + dlsch0_harq = dlsch[codeword_TB0]->harq_processes[harq_pid]; + dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid]; + } + else if ((dlsch[0]->harq_processes[harq_pid]->status == ACTIVE) && + (dlsch[1]->harq_processes[harq_pid]->status != ACTIVE) ) { + codeword_TB0 = dlsch[0]->harq_processes[harq_pid]->codeword; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch1_harq = NULL; + codeword_TB1 = -1; + } + else if ((dlsch[0]->harq_processes[harq_pid]->status != ACTIVE) && + (dlsch[1]->harq_processes[harq_pid]->status == ACTIVE) ){ + codeword_TB1 = dlsch[1]->harq_processes[harq_pid]->codeword; + dlsch0_harq = dlsch[1]->harq_processes[harq_pid]; + dlsch1_harq = NULL; + codeword_TB0 = -1; + } + else { + LOG_E(PHY,"[UE][FATAL] Frame %d subframe %d: no active DLSCH\n",ue->proc.proc_rxtx[0].frame_rx,subframe); + return(-1); + } beamforming_mode = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]; break; @@ -125,7 +185,13 @@ int rx_pdsch(PHY_VARS_UE *ue, return(-1); break; } +#ifdef DEBUG_HARQ + printf("[DEMOD] MIMO mode = %d\n", dlsch0_harq->mimo_mode); + printf("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1); +#endif + DevAssert(dlsch0_harq); + round = dlsch0_harq->round; if (eNB_id > 2) { LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id); @@ -138,7 +204,7 @@ int rx_pdsch(PHY_VARS_UE *ue, } if (!dlsch[0]) { - LOG_W(PHY,"dlsch_demodulation.c: Null dlsch pointer\n"); + LOG_W(PHY,"dlsch_demodulation.c: Null dlsch_ue pointer\n"); return(-1); } @@ -152,17 +218,33 @@ int rx_pdsch(PHY_VARS_UE *ue, return(-1); } - if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) || ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) rballoc = dlsch0_harq->rb_alloc_odd; else rballoc = dlsch0_harq->rb_alloc_even; + + if (dlsch0_harq->mimo_mode>DUALSTREAM_PUSCH_PRECODING) { + LOG_E(PHY,"This transmission mode is not yet supported!\n"); + return(-1); + } + + + + if ((dlsch0_harq->mimo_mode==LARGE_CDD) || ((dlsch0_harq->mimo_mode>=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode<=DUALSTREAM_PUSCH_PRECODING))) { + DevAssert(dlsch1_harq); + if (eNB_id!=eNB_id_i) { + LOG_E(PHY,"TM3/TM4 requires to set eNB_id==eNB_id_i!\n"); + return(-1); + } + } + if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) { #ifdef DEBUG_DLSCH_MOD LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0],dlsch0_harq->rb_alloc_even[0]); #endif + nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id], pdsch_vars[eNB_id]->rxdataF_ext, @@ -173,11 +255,18 @@ int rx_pdsch(PHY_VARS_UE *ue, symbol, subframe, ue->high_speed_flag, - frame_parms); + frame_parms, + dlsch0_harq->mimo_mode); +#ifdef DEBUG_DLSCH_MOD + printf("dlsch: using pmi %lx, rb_alloc %x, pmi_ext ",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),*rballoc); + for (rb=0;rb<nb_rb;rb++) + printf("%d",pdsch_vars[eNB_id]->pmi_ext[rb]); + printf("\n"); +#endif - if (dual_stream_flag==1) { - if (eNB_id_i<ue->n_connected_eNB) - nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, + if (rx_type >= rx_IC_single_stream) { + if (eNB_id_i<ue->n_connected_eNB) // we are in TM5 + nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id_i], pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, @@ -187,7 +276,8 @@ int rx_pdsch(PHY_VARS_UE *ue, symbol, subframe, ue->high_speed_flag, - frame_parms); + frame_parms, + dlsch0_harq->mimo_mode); else nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id], @@ -199,7 +289,8 @@ int rx_pdsch(PHY_VARS_UE *ue, symbol, subframe, ue->high_speed_flag, - frame_parms); + frame_parms, + dlsch0_harq->mimo_mode); } } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0 nb_rb = dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, @@ -214,8 +305,8 @@ int rx_pdsch(PHY_VARS_UE *ue, ue->high_speed_flag, frame_parms); - if (dual_stream_flag==1) { - if (eNB_id_i<ue->n_connected_eNB) + if (rx_type==rx_IC_single_stream) { + if (eNB_id_i<ue->n_connected_eNB) nb_rb = dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id_i], pdsch_vars[eNB_id_i]->rxdataF_ext, @@ -227,7 +318,7 @@ int rx_pdsch(PHY_VARS_UE *ue, subframe, ue->high_speed_flag, frame_parms); - + else nb_rb = dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF, common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id], pdsch_vars[eNB_id_i]->rxdataF_ext, @@ -237,7 +328,7 @@ int rx_pdsch(PHY_VARS_UE *ue, rballoc, symbol, subframe, - ue->high_speed_flag, + ue->high_speed_flag, frame_parms); } } else if (beamforming_mode==7) { //else if beamforming_mode == 7 @@ -245,58 +336,144 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_bf_ch_estimates, pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, - rballoc, + rballoc, symbol, subframe, ue->high_speed_flag, frame_parms); - + } else if(beamforming_mode>7) { - LOG_W(PHY,"dlsch_demodulation:beamforming mode not supported yet.\n"); + LOG_W(PHY,"dlsch_demodulation: beamforming mode not supported yet.\n"); } - // printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id); + //printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id); if (nb_rb==0) { LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n"); return(-1); } - /* - // DL power control: Scaling of Channel estimates for PDSCH + +#ifdef DEBUG_PHY + LOG_D(PHY,"[DLSCH] nb_rb %d log2_maxh = %d (%d,%d)\n",nb_rb,pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs); + LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); +#endif + + aatx = frame_parms->nb_antenna_ports_eNB; + aarx = frame_parms->nb_antennas_rx; + dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - frame_parms, - dlsch, - symbol, - nb_rb); - */ + frame_parms, + dlsch, + symbol, + nb_rb); + + if ((dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) && + (rx_type==rx_IC_single_stream) && + (eNB_id_i==ue->n_connected_eNB) && + (dlsch0_harq->dl_power_off==0) + ) // TM5 two-user + { + dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + frame_parms, + dlsch, + symbol, + nb_rb); + } + if (first_symbol_flag==1) { - if (beamforming_mode==0) - dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + if (beamforming_mode==0){ + if (dlsch0_harq->mimo_mode<LARGE_CDD) { + dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, nb_rb); + 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,avg[(aatx<<1)+aarx]); + + pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1; + } + else if ((dlsch0_harq->mimo_mode == LARGE_CDD) || + ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && + (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))) + { + dlsch_channel_level_TM34(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + frame_parms, + pdsch_vars[eNB_id]->pmi_ext, + avg_0, + avg_1, + symbol, + nb_rb, + dlsch0_harq->mimo_mode); + + LOG_D(PHY,"Channel Level TM34 avg_0 %d, avg_1 %d, rx_type %d, rx_standard %d, interf_unaw_shift %d \n", avg_0[0], + avg_1[0], rx_type, rx_standard, interf_unaw_shift); + if (rx_type>rx_standard) { + avg_0[0] = (log2_approx(avg_0[0])/2) + dlsch_demod_shift;// + 2 ;//+ 4; + avg_1[0] = (log2_approx(avg_1[0])/2) + dlsch_demod_shift;// + 2 ;//+ 4; + pdsch_vars[eNB_id]->log2_maxh0 = cmax(avg_0[0],0); + pdsch_vars[eNB_id]->log2_maxh1 = cmax(avg_1[0],0); + //printf("TM4 I-A log2_maxh0 = %d\n", pdsch_vars[eNB_id]->log2_maxh0); + //printf("TM4 I-A log2_maxh1 = %d\n", pdsch_vars[eNB_id]->log2_maxh1); + } + else { + avg_0[0] = (log2_approx(avg_0[0])/2) - 13 + interf_unaw_shift; + avg_1[0] = (log2_approx(avg_1[0])/2) - 13 + interf_unaw_shift; + pdsch_vars[eNB_id]->log2_maxh0 = cmax(avg_0[0],0); + pdsch_vars[eNB_id]->log2_maxh1 = cmax(avg_1[0],0); + //printf("TM4 I-UA log2_maxh0 = %d\n", pdsch_vars[eNB_id]->log2_maxh0); + //printf("TM4 I-UA log2_maxh1 = %d\n", pdsch_vars[eNB_id]->log2_maxh1); + } + } + else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) {// single-layer precoding (TM5, TM6) + if ((rx_type==rx_IC_single_stream) && (eNB_id_i==ue->n_connected_eNB) && (dlsch0_harq->dl_power_off==0)) { + dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + frame_parms, + pdsch_vars[eNB_id]->pmi_ext, + avg, + symbol, + nb_rb); + avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]; + pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); + + } + else if (dlsch0_harq->dl_power_off==1) { //TM6 + + dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + frame_parms, + avg, + symbol, + nb_rb); + + 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,avg[(aatx<<1)+aarx]); + + pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; + pdsch_vars[eNB_id]->log2_maxh++; + + } + } + + } else if (beamforming_mode==7) dlsch_channel_level_TM7(pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, - frame_parms, - avg, - symbol, - nb_rb); - + frame_parms, + avg, + symbol, + nb_rb); #ifdef DEBUG_PHY - LOG_D(PHY,"[DLSCH] avg[0] %d\n",avg[0]); + LOG_I(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d [log2_maxh0 %d log2_maxh1 %d] (%d,%d)\n", + frame%1024,subframe, pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[eNB_id]->log2_maxh0, + pdsch_vars[eNB_id]->log2_maxh1, + avg[0],avgs); + LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); #endif - - // the channel gain should be the effective gain of precoding + channel - // however lets be more conservative and set maxh = nb_tx*nb_rx*max(h_i) - // in case of precoding we add an additional factor of two for the precoding gain - 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,avg[(aatx<<1)+aarx]); - - // avgs = cmax(avgs,avg[(aarx<<1)+aatx]); + } #if T_TRACER if (type == PDSCH) @@ -306,40 +483,8 @@ int rx_pdsch(PHY_VARS_UE *ue, } #endif - pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1; - // + log2_approx(frame_parms->nb_antenna_ports_eNB-1) //-1 because log2_approx counts the number of bits - // + log2_approx(frame_parms->nb_antennas_rx-1); - - if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) && - (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) && - (dlsch0_harq->dl_power_off==1)) // we are in TM 6 - pdsch_vars[eNB_id]->log2_maxh++; - - // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above - /* K = Nb_rx in TM1 - Nb_tx*Nb_rx in TM2,4,5 - Nb_tx^2*Nb_rx in TM6 */ - /* - K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1 - if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) && - (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) && - (dlsch0_harq->dl_power_off==1)) // we are in TM 6 - K *= frame_parms->nb_antenna_ports_eNB; - - pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2); - */ - -#ifdef DEBUG_PHY - LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs); - LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); -#endif - } - - aatx = frame_parms->nb_antenna_ports_eNB; - aarx = frame_parms->nb_antennas_rx; - - if (dlsch0_harq->mimo_mode<LARGE_CDD) {// SISO or ALAMOUTI - +// Now channel compensation + if (dlsch0_harq->mimo_mode<LARGE_CDD) { dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, @@ -352,18 +497,13 @@ int rx_pdsch(PHY_VARS_UE *ue, dlsch0_harq->Qm, nb_rb, pdsch_vars[eNB_id]->log2_maxh, - phy_measurements); // log2_maxh+I0_shift -#ifdef DEBUG_PHY - - if (symbol==5) - write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - -#endif - - if ((dual_stream_flag==1) && + measurements); // log2_maxh+I0_shift + /*if (symbol == 5) { + write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + } */ + if ((rx_type==rx_IC_single_stream) && (eNB_id_i<ue->n_connected_eNB)) { - // get MF output for interfering stream - dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext, + dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_mag0, pdsch_vars[eNB_id_i]->dl_ch_magb0, @@ -375,104 +515,79 @@ int rx_pdsch(PHY_VARS_UE *ue, i_mod, nb_rb, pdsch_vars[eNB_id]->log2_maxh, - phy_measurements); // log2_maxh+I0_shift + measurements); // log2_maxh+I0_shift #ifdef DEBUG_PHY - if (symbol == 5) { write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } - #endif - // compute correlation between signal and interference channels dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->log2_maxh); } - } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3 - // LOG_I(PHY,"Running PDSCH RX for TM3\n"); - if (frame_parms->nb_antenna_ports_eNB == 2) { - if (first_symbol_flag==1) { - // effective channel of desired user is always stronger than interfering eff. channel - dlsch_channel_level_TM3(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - frame_parms, - avg, symbol, nb_rb); - - // LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->mcs>>1)-1]); - avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1]; - - pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); - // printf("log2_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh); - } - - dlsch_channel_compensation_TM3(frame_parms, + } else if ((dlsch0_harq->mimo_mode == LARGE_CDD) || ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && + (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))){ + dlsch_channel_compensation_TM34(frame_parms, pdsch_vars[eNB_id], - phy_measurements, + measurements, eNB_id, symbol, dlsch0_harq->Qm, dlsch1_harq->Qm, + harq_pid, dlsch0_harq->round, + dlsch0_harq->mimo_mode, nb_rb, - pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->log2_maxh0, + pdsch_vars[eNB_id]->log2_maxh1); + /* if (symbol == 5) { + write_output("rxF_comp_d00.m","rxF_c_d00",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM + write_output("rxF_comp_d01.m","rxF_c_d01",&pdsch_vars[eNB_id]->rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rxF_comp_d10.m","rxF_c_d10",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rxF_comp_d11.m","rxF_c_d11",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM + } */ // compute correlation between signal and interference channels (rho12 and rho21) - dlsch_dual_stream_correlation(frame_parms, + dlsch_dual_stream_correlation(frame_parms, // this is doing h11'*h12 and h21'*h22 symbol, nb_rb, pdsch_vars[eNB_id]->dl_ch_estimates_ext, &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->log2_maxh); - dlsch_dual_stream_correlation(frame_parms, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->log2_maxh0); + //printf("rho stream1 =%d\n", &pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round] ); + //to be optimized (just take complex conjugate) + dlsch_dual_stream_correlation(frame_parms, // this is doing h12'*h11 and h22'*h21 symbol, nb_rb, &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->log2_maxh1); + // printf("rho stream2 =%d\n",&pdsch_vars[eNB_id]->dl_ch_rho2_ext ); //printf("TM3 log2_maxh : %d\n",pdsch_vars[eNB_id]->log2_maxh); - - } else { - LOG_E(PHY, "only 2 tx antennas supported for TM3\n"); - } - } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) { // single-layer precoding (TM5, TM6), potentially TM4 (Single-codeword) - // printf("Channel compensation for precoding\n"); - // if ((dual_stream_flag==1) && (eNB_id_i==NUMBER_OF_CONNECTED_eNB_MAX)) { - if ((dual_stream_flag==1) && (eNB_id_i==ue->n_connected_eNB)) { // TM5 two-user - - // Scale the channel estimates for interfering stream - - dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - frame_parms, - dlsch, - symbol, - nb_rb); - - /* compute new log2_maxh for effective channel */ - if (first_symbol_flag==1) { - // effective channel of desired user is always stronger than interfering eff. channel - dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb); - - // LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]); - avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]; - - pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); - //printf("log1_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh); - } - - dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, + /* if (symbol == 5) { + write_output("rho0_0.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM + write_output("rho2_0.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rho0_1.m.m","rho0_1",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rho2_1.m","rho2_1",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM + } */ + + } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) {// single-layer precoding (TM5, TM6) + if ((rx_type==rx_IC_single_stream) && (eNB_id_i==ue->n_connected_eNB) && (dlsch0_harq->dl_power_off==0)) { + dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->pmi_ext, frame_parms, - phy_measurements, + measurements, eNB_id, symbol, dlsch0_harq->Qm, @@ -480,33 +595,24 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->log2_maxh, dlsch0_harq->dl_power_off); - // if interference source is MU interference, assume opposite precoder was used at eNB - - // calculate opposite PMI - for (rb=0; rb<nb_rb; rb++) { - switch(pdsch_vars[eNB_id]->pmi_ext[rb]) { - case 0: - pdsch_vars[eNB_id_i]->pmi_ext[rb]=1; - break; - - case 1: - pdsch_vars[eNB_id_i]->pmi_ext[rb]=0; - break; - - case 2: - pdsch_vars[eNB_id_i]->pmi_ext[rb]=3; - break; - - case 3: - pdsch_vars[eNB_id_i]->pmi_ext[rb]=2; - break; - } - - // if (rb==0) + for (rb=0; rb<nb_rb; rb++) { + switch(pdsch_vars[eNB_id]->pmi_ext[rb]) { + case 0: + pdsch_vars[eNB_id_i]->pmi_ext[rb]=1; + break; + case 1: + pdsch_vars[eNB_id_i]->pmi_ext[rb]=0; + break; + case 2: + pdsch_vars[eNB_id_i]->pmi_ext[rb]=3; + break; + case 3: + pdsch_vars[eNB_id_i]->pmi_ext[rb]=2; + break; + } + // if (rb==0) // printf("pmi %d, pmi_i %d\n",pdsch_vars[eNB_id]->pmi_ext[rb],pdsch_vars[eNB_id_i]->pmi_ext[rb]); - } - dlsch_channel_compensation_TM56(pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_mag0, @@ -514,32 +620,27 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id_i]->rxdataF_comp0, pdsch_vars[eNB_id_i]->pmi_ext, frame_parms, - phy_measurements, + measurements, eNB_id_i, symbol, i_mod, nb_rb, pdsch_vars[eNB_id]->log2_maxh, dlsch0_harq->dl_power_off); - #ifdef DEBUG_PHY - if (symbol==5) { write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } - #endif - dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->log2_maxh); - - } else { + } else if (dlsch0_harq->dl_power_off==1) { dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, @@ -547,66 +648,70 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->pmi_ext, frame_parms, - phy_measurements, + measurements, eNB_id, symbol, dlsch0_harq->Qm, nb_rb, pdsch_vars[eNB_id]->log2_maxh, 1); - } - } else if (dlsch0_harq->mimo_mode==TM7) { //TM7 - dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->rxdataF_comp0, - (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, - frame_parms, - symbol, - first_symbol_flag, - get_Qm(dlsch0_harq->mcs), - nb_rb, - //9, - pdsch_vars[eNB_id]->log2_maxh, - phy_measurements); // log2_maxh+I0_shift + } + + + } else if (dlsch0_harq->mimo_mode==TM7) { //TM7 + + dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, + frame_parms, + symbol, + first_symbol_flag, + get_Qm(dlsch0_harq->mcs), + nb_rb, + //9, + pdsch_vars[eNB_id]->log2_maxh, + measurements); // log2_maxh+I0_shift } - // printf("MRC\n"); - if (frame_parms->nb_antennas_rx > 1) { - if (dlsch0_harq->mimo_mode == LARGE_CDD) { +// MRC + + + if (frame_parms->nb_antennas_rx > 1) { + if ((dlsch0_harq->mimo_mode == LARGE_CDD) || + ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && + (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))){ // TM3 or TM4 if (frame_parms->nb_antenna_ports_eNB == 2) { - dlsch_detection_mrc(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->rho, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->dl_ch_mag1, - pdsch_vars[eNB_id]->dl_ch_magb1, - symbol, - nb_rb, - dual_stream_flag); + dlsch_detection_mrc_TM34(frame_parms, + pdsch_vars[eNB_id], + harq_pid, + dlsch0_harq->round, + symbol, + nb_rb, + 1); + /* if (symbol == 5) { + write_output("rho0_mrc.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM + write_output("rho2_mrc.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + } */ } } else { - dlsch_detection_mrc(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id_i]->rxdataF_comp0, pdsch_vars[eNB_id]->rho, - pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id_i]->dl_ch_mag0, pdsch_vars[eNB_id_i]->dl_ch_magb0, symbol, nb_rb, - dual_stream_flag); + rx_type==rx_IC_single_stream); } } - // printf("Combining"); if ((dlsch0_harq->mimo_mode == SISO) || ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) && @@ -620,122 +725,300 @@ int rx_pdsch(PHY_VARS_UE *ue, nb_rb); */ } else if (dlsch0_harq->mimo_mode == ALAMOUTI) { - dlsch_alamouti(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol, nb_rb); - } - else if (dlsch0_harq->mimo_mode == LARGE_CDD) { - - } else { - LOG_W(PHY,"dlsch_rx: Unknown MIMO mode\n"); - return (-1); + // printf("LLR"); + if ((dlsch0_harq->mimo_mode == LARGE_CDD) || + ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && + (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))) { + rxdataF_comp_ptr = pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round]; + dl_ch_mag_ptr = pdsch_vars[eNB_id]->dl_ch_mag1[harq_pid][round]; + } + else { + rxdataF_comp_ptr = pdsch_vars[eNB_id_i]->rxdataF_comp0; + dl_ch_mag_ptr = pdsch_vars[eNB_id_i]->dl_ch_mag0; + //i_mod should have been passed as a parameter } - // printf("LLR"); + //printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol); switch (dlsch0_harq->Qm) { case 2 : - if (dlsch0_harq->mimo_mode != LARGE_CDD) { - if (dual_stream_flag == 0) + if ((rx_type==rx_standard) || (codeword_TB0 == -1) || (codeword_TB1 == -1)) { dlsch_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, + symbol, + first_symbol_flag, + nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); - else if (i_mod == 2) { - dlsch_qpsk_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - } else if (i_mod == 4) { - dlsch_qpsk_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - } else { - dlsch_qpsk_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - + } + else if (rx_type >= rx_IC_single_stream) { + if (dlsch1_harq->Qm == 2) { + dlsch_qpsk_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_qpsk_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else if (dlsch1_harq->Qm == 4) { + dlsch_qpsk_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_16qam_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else { + dlsch_qpsk_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_64qam_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } } - } else { // TM3 - DevAssert(dlsch1_harq); - + break; + case 4 : + if ((rx_type==rx_standard ) || (codeword_TB0 == -1) || (codeword_TB1 == -1)) { + dlsch_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + pdsch_vars[eNB_id]->llr128, + beamforming_mode); + } + else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { - /* dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - */ - dlsch_qpsk_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - dlsch_qpsk_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } else if (dlsch1_harq->Qm == 4) { - dlsch_qpsk_16qam_llr(frame_parms, + dlsch_16qam_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - pdsch_vars[eNB_id]->dl_ch_mag1, - pdsch_vars[eNB_id]->dl_ch_rho_ext, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); - } else { - dlsch_qpsk_64qam_llr(frame_parms, + if (rx_type==rx_IC_dual_stream) { + dlsch_qpsk_16qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else if (dlsch1_harq->Qm == 4) { + dlsch_16qam_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_16qam_16qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else { + dlsch_16qam_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_64qam_16qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0, + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + } + break; + case 6 : + //printf("LLR rx_type %d cw0 %d cw1 %d symbol %d first symbol %d nb_rb %d rballoceven %d sfn %d beamforming_mode %d\n", + // rx_type,codeword_TB0,codeword_TB1,symbol,first_symbol_flag,nb_rb,dlsch0_harq->rb_alloc_even,subframe,beamforming_mode); + if ((rx_type==rx_standard) || (codeword_TB0 == -1) || (codeword_TB1 == -1)) { + dlsch_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + pdsch_vars[eNB_id]->llr128, + beamforming_mode); + } + else if (rx_type >= rx_IC_single_stream) { + if (dlsch1_harq->Qm == 2) { + dlsch_64qam_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - pdsch_vars[eNB_id]->dl_ch_mag1, - pdsch_vars[eNB_id]->dl_ch_rho_ext, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128); - + if (rx_type==rx_IC_dual_stream) { + dlsch_qpsk_64qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else if (dlsch1_harq->Qm == 4) { + dlsch_64qam_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_16qam_64qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else { + dlsch_64qam_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + dlsch_64qam_64qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } } } - break; - - case 4 : - if (dual_stream_flag == 0) { + default: + LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); + return(-1); + break; + } + if (dlsch1_harq) { + switch (get_Qm(dlsch1_harq->mcs)) { + case 2 : + if (rx_type==rx_standard) { + dlsch_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + pdsch_vars[eNB_id]->llr128, + beamforming_mode); + } + break; + case 4: + if (rx_type==rx_standard) { dlsch_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->llr[0], @@ -744,44 +1027,10 @@ int rx_pdsch(PHY_VARS_UE *ue, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); - } else if (i_mod == 2) { - dlsch_16qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - } else if (i_mod == 4) { - dlsch_16qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - } else { - dlsch_16qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); } - break; - case 6 : - if (dual_stream_flag == 0) { + if (rx_type==rx_standard) { dlsch_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->llr[0], @@ -791,48 +1040,53 @@ int rx_pdsch(PHY_VARS_UE *ue, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); - } else if (i_mod == 2) { - dlsch_64qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - } else if (i_mod == 4) { - dlsch_64qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - - } else { - dlsch_64qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext, - pdsch_vars[eNB_id]->llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128); - } - + } break; - default: LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); return(-1); break; } + } + +// Please keep it: useful for debugging +#if 0 + if( (symbol == 13) && (subframe==0) && (dlsch0_harq->Qm == 6) /*&& (nb_rb==25)*/) + { + LOG_E(PHY,"Dump Phy Chan Est \n"); + if(1) + { +#if 1 + write_output("rxdataF0.m" , "rxdataF0", &common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0][0],14*frame_parms->ofdm_symbol_size,1,1); + //write_output("rxdataF1.m" , "rxdataF1", &common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0][0],14*frame_parms->ofdm_symbol_size,1,1); + write_output("dl_ch_estimates00.m", "dl_ch_estimates00", &common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][0][0],14*frame_parms->ofdm_symbol_size,1,1); + //write_output("dl_ch_estimates01.m", "dl_ch_estimates01", &common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][1][0],14*frame_parms->ofdm_symbol_size,1,1); + //write_output("dl_ch_estimates10.m", "dl_ch_estimates10", &common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2][0],14*frame_parms->ofdm_symbol_size,1,1); + //write_output("dl_ch_estimates11.m", "dl_ch_estimates11", &common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][3][0],14*frame_parms->ofdm_symbol_size,1,1); + + + //write_output("rxdataF_ext00.m" , "rxdataF_ext00", &pdsch_vars[eNB_id]->rxdataF_ext[0][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("rxdataF_ext01.m" , "rxdataF_ext01", &pdsch_vars[eNB_id]->rxdataF_ext[1][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("rxdataF_ext10.m" , "rxdataF_ext10", &pdsch_vars[eNB_id]->rxdataF_ext[2][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("rxdataF_ext11.m" , "rxdataF_ext11", &pdsch_vars[eNB_id]->rxdataF_ext[3][0],14*frame_parms->N_RB_DL*12,1,1); + write_output("dl_ch_estimates_ext00.m", "dl_ch_estimates_ext00", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[0][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("dl_ch_estimates_ext01.m", "dl_ch_estimates_ext01", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[1][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("dl_ch_estimates_ext10.m", "dl_ch_estimates_ext10", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[2][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("dl_ch_estimates_ext11.m", "dl_ch_estimates_ext11", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[3][0],14*frame_parms->N_RB_DL*12,1,1); + write_output("rxdataF_comp00.m","rxdataF_comp00", &pdsch_vars[eNB_id]->rxdataF_comp0[0][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("rxdataF_comp01.m","rxdataF_comp01", &pdsch_vars[eNB_id]->rxdataF_comp0[1][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("rxdataF_comp10.m","rxdataF_comp10", &pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][0],14*frame_parms->N_RB_DL*12,1,1); + //write_output("rxdataF_comp11.m","rxdataF_comp11", &pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][0],14*frame_parms->N_RB_DL*12,1,1); +#endif + write_output("llr0.m","llr0", &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("llr1.m","llr1", &pdsch_vars[eNB_id]->llr[1][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); + + + AssertFatal(0," "); + } + + } +#endif #if T_TRACER T(T_UE_PHY_PDSCH_IQ, T_INT(eNB_id), T_INT(ue->Mod_id), T_INT(frame%1024), @@ -843,6 +1097,7 @@ int rx_pdsch(PHY_VARS_UE *ue, #endif return(0); + } //============================================================================================== @@ -861,7 +1116,7 @@ void dlsch_channel_compensation(int **rxdataF_ext, unsigned char mod_order, unsigned short nb_rb, unsigned char output_shift, - PHY_MEASUREMENTS *phy_measurements) + PHY_MEASUREMENTS *measurements) { #if defined(__i386) || defined(__x86_64) @@ -919,9 +1174,9 @@ void dlsch_channel_compensation(int **rxdataF_ext, dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); - //print_ints("Re(ch):",(int16_t*)&mmtmpD0); - //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); - //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); + //print_ints("Re(ch):",(int16_t*)&mmtmpD0); + //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); + //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); @@ -1107,7 +1362,7 @@ void dlsch_channel_compensation(int **rxdataF_ext, } if (first_symbol_flag==1) { - phy_measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); + measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); } } } @@ -1157,168 +1412,166 @@ void dlsch_channel_compensation(int **rxdataF_ext, dl_ch_mag128b = (int16x8_t*)&dl_ch_magb[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; - + for (rb=0; rb<nb_rb; rb++) { - if (mod_order>2) { - // get channel amplitude if not QPSK - mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128[0]); - // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits - mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128[1]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits - mmtmpD0 = vmull_s16(dl_ch128[2], dl_ch128[2]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128[3]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch128[4], dl_ch128[4]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch128[5], dl_ch128[5]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - } - - dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); - dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); - dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); - dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); - - if (pilots==0) { - dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); - dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); - } - } - - mmtmpD0 = vmull_s16(dl_ch128[0], rxdataF128[0]); - //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] - mmtmpD1 = vmull_s16(dl_ch128[1], rxdataF128[1]); - //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] - - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[0],*(int16x4_t*)conj)), rxdataF128[0]); - //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[1],*(int16x4_t*)conj)), rxdataF128[1]); - //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp128[0] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - mmtmpD0 = vmull_s16(dl_ch128[2], rxdataF128[2]); - mmtmpD1 = vmull_s16(dl_ch128[3], rxdataF128[3]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[2],*(int16x4_t*)conj)), rxdataF128[2]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[3],*(int16x4_t*)conj)), rxdataF128[3]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch128[4], rxdataF128[4]); - mmtmpD1 = vmull_s16(dl_ch128[5], rxdataF128[5]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), rxdataF128[4]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), rxdataF128[5]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - - dl_ch128+=6; - dl_ch_mag128+=3; - dl_ch_mag128b+=3; - rxdataF128+=6; - rxdataF_comp128+=3; - - } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less - dl_ch128+=4; - dl_ch_mag128+=2; - dl_ch_mag128b+=2; - rxdataF128+=4; - rxdataF_comp128+=2; - } + if (mod_order>2) { + // get channel amplitude if not QPSK + mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128[0]); + // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits + mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128[1]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits + mmtmpD0 = vmull_s16(dl_ch128[2], dl_ch128[2]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128[3]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + if (pilots==0) { + mmtmpD0 = vmull_s16(dl_ch128[4], dl_ch128[4]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch128[5], dl_ch128[5]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + } + + dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); + dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); + dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); + dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); + + if (pilots==0) { + dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); + dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); + } + } + + mmtmpD0 = vmull_s16(dl_ch128[0], rxdataF128[0]); + //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] + mmtmpD1 = vmull_s16(dl_ch128[1], rxdataF128[1]); + //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] + + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[0],*(int16x4_t*)conj)), rxdataF128[0]); + //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[1],*(int16x4_t*)conj)), rxdataF128[1]); + //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp128[0] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + mmtmpD0 = vmull_s16(dl_ch128[2], rxdataF128[2]); + mmtmpD1 = vmull_s16(dl_ch128[3], rxdataF128[3]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[2],*(int16x4_t*)conj)), rxdataF128[2]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[3],*(int16x4_t*)conj)), rxdataF128[3]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + if (pilots==0) { + mmtmpD0 = vmull_s16(dl_ch128[4], rxdataF128[4]); + mmtmpD1 = vmull_s16(dl_ch128[5], rxdataF128[5]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), rxdataF128[4]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), rxdataF128[5]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + + dl_ch128+=6; + dl_ch_mag128+=3; + dl_ch_mag128b+=3; + rxdataF128+=6; + rxdataF_comp128+=3; + + } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less + dl_ch128+=4; + dl_ch_mag128+=2; + dl_ch_mag128b+=2; + rxdataF128+=4; + rxdataF_comp128+=2; + } } } } - + if (rho) { for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { rho128 = (int16x4x2_t*)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { - mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128_2[0]); - mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128_2[1]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[0],*(int16x4_t*)conj)), dl_ch128_2[0]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[1],*(int16x4_t*)conj)), dl_ch128_2[1]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rho128[0] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - mmtmpD0 = vmull_s16(dl_ch128[2], dl_ch128_2[2]); - mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128_2[3]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[2],*(int16x4_t*)conj)), dl_ch128_2[2]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[3],*(int16x4_t*)conj)), dl_ch128_2[3]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rho128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128_2[0]); - mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128_2[1]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), dl_ch128_2[4]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), dl_ch128_2[5]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rho128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - - dl_ch128+=6; - dl_ch128_2+=6; - rho128+=3; + mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128_2[0]); + mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128_2[1]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[0],*(int16x4_t*)conj)), dl_ch128_2[0]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[1],*(int16x4_t*)conj)), dl_ch128_2[1]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rho128[0] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + mmtmpD0 = vmull_s16(dl_ch128[2], dl_ch128_2[2]); + mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128_2[3]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[2],*(int16x4_t*)conj)), dl_ch128_2[2]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[3],*(int16x4_t*)conj)), dl_ch128_2[3]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rho128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128_2[0]); + mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128_2[1]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), dl_ch128_2[4]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), dl_ch128_2[5]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rho128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + + dl_ch128+=6; + dl_ch128_2+=6; + rho128+=3; } - + if (first_symbol_flag==1) { - phy_measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); + measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); } } } #endif } - - #if defined(__x86_64__) || defined(__i386__) void prec2A_TM56_128(unsigned char pmi,__m128i *ch0,__m128i *ch1) @@ -1364,62 +1617,63 @@ void prec2A_TM56_128(unsigned char pmi,__m128i *ch0,__m128i *ch1) _mm_empty(); _m_empty(); } - #elif defined(__arm__) -void prec2A_TM56_128(unsigned char pmi,int16x8_t* ch0,int16x8_t* ch1) { +void prec2A_TM56_128(unsigned char pmi,__m128i *ch0,__m128i *ch1) { - int16x8_t amp; - int16_t conj[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; + // sqrt(2) is already taken into account in computation sqrt_rho_a, sqrt_rho_b, + //so removed it - amp = vmovq_n_s16(ONE_OVER_SQRT2_Q15); + //__m128i amp; + //amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); switch (pmi) { + case 0 : // +1 +1 // print_shorts("phase 0 :ch0",ch0); // print_shorts("phase 0 :ch1",ch1); - ch0[0] = vqaddq_s16(ch0[0],ch1[0]); + ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; - case 1 : // +1 -1 // print_shorts("phase 1 :ch0",ch0); // print_shorts("phase 1 :ch1",ch1); - ch0[0] = vqsubq_s16(ch0[0],ch1[0]); + ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); // print_shorts("phase 1 :ch0-ch1",ch0); break; - case 2 : // +1 +j - ch1[0] = vrev32q_s16(vmulq_s16(ch1[0],*(int16x8_t*)conj)); - ch0[0] = vqsubq_s16(ch0[0],ch1[0]); + ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); + ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); + ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); + ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); + break; // +1 -j - case 3 : - ch1[0] = vrev32q_s16(vmulq_s16(ch1[0],*(int16x8_t*)conj)); - ch0[0] = vqaddq_s16(ch0[0],ch1[0]); + ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); + ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); + ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); + ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; } - - ch0[0] = vqdmulhq_s16(ch0[0],amp); -} -#endif + //ch0[0] = _mm_mulhi_epi16(ch0[0],amp); + //ch0[0] = _mm_slli_epi16(ch0[0],1); + _mm_empty(); + _m_empty(); +} +#endif // precoding is stream 0 .5(1,1) .5(1,-1) .5(1,1) .5(1,-1) // stream 1 .5(1,-1) .5(1,1) .5(1,-1) .5(1,1) // store "precoded" channel for stream 0 in ch0, stream 1 in ch1 short TM3_prec[8]__attribute__((aligned(16))) = {1,1,-1,-1,1,1,-1,-1} ; -#if defined(__x86_64__) || defined(__i386__) - -static inline void prec2A_TM3_128(__m128i *ch0,__m128i *ch1) __attribute__((always_inline)); -static inline void prec2A_TM3_128(__m128i *ch0,__m128i *ch1) -{ +void prec2A_TM3_128(__m128i *ch0,__m128i *ch1) { - // __m128i amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); + __m128i amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); __m128i tmp0,tmp1; - + //_mm_mulhi_epi16 // print_shorts("prec2A_TM3 ch0 (before):",ch0); // print_shorts("prec2A_TM3 ch1 (before):",ch1); @@ -1430,89 +1684,79 @@ static inline void prec2A_TM3_128(__m128i *ch0,__m128i *ch1) ch0[0] = _mm_adds_epi16(ch0[0],tmp1); ch1[0] = _mm_subs_epi16(tmp0,tmp1); + ch0[0] = _mm_mulhi_epi16(ch0[0],amp); + ch0[0] = _mm_slli_epi16(ch0[0],1); + + ch1[0] = _mm_mulhi_epi16(ch1[0],amp); + ch1[0] = _mm_slli_epi16(ch1[0],1); // print_shorts("prec2A_TM3 ch0 (mid):",&tmp0); // print_shorts("prec2A_TM3 ch1 (mid):",ch1); + //ch0[0] = _mm_mulhi_epi16(ch0[0],amp); + //ch0[0] = _mm_slli_epi16(ch0[0],1); + //ch1[0] = _mm_mulhi_epi16(ch1[0],amp); + //ch1[0] = _mm_slli_epi16(ch1[0],1); - ch0[0] = _mm_srai_epi16(ch0[0],1); - ch1[0] = _mm_srai_epi16(ch1[0],1); + //ch0[0] = _mm_srai_epi16(ch0[0],1); + //ch1[0] = _mm_srai_epi16(ch1[0],1); // print_shorts("prec2A_TM3 ch0 (after):",ch0); // print_shorts("prec2A_TM3 ch1 (after):",ch1); + _mm_empty(); + _m_empty(); } -#elif defined(__arm__) - -void prec2A_TM3_128(int16x8_t* ch0, int16x8_t* ch1) -{ - - int16x8_t tmp0,tmp1; - - tmp0 = ch0[0]; - tmp1 = vmulq_s16(ch1[0],((int16x8_t*)&TM3_prec)[0]); - ch0[0] = vhaddq_s16(ch0[0],tmp1); - ch1[0] = vhsubq_s16(tmp0,tmp1); -} - -#endif - // pmi = 0 => stream 0 (1,1), stream 1 (1,-1) // pmi = 1 => stream 0 (1,j), stream 2 (1,-j) -#if defined(__x86_64__) || defined(__i386__) +void prec2A_TM4_128(int pmi,__m128i *ch0,__m128i *ch1) { -void prec2A_TM4_128(int pmi,__m128i *ch0,__m128i *ch1) -{ +// sqrt(2) is already taken into account in computation sqrt_rho_a, sqrt_rho_b, +//so divide by 2 is replaced by divide by sqrt(2). - __m128i amp; - amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); + // printf ("demod pmi=%d\n", pmi); + __m128i amp; + amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); __m128i tmp0,tmp1; - if (pmi == 0) { - ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); - ch1[0] = _mm_subs_epi16(ch0[0],ch1[0]); - } else { + // print_shorts("prec2A_TM4 ch0 (before):",ch0); + // print_shorts("prec2A_TM4 ch1 (before):",ch1); + + if (pmi == 0) { //[1 1;1 -1] + tmp0 = ch0[0]; + tmp1 = ch1[0]; + ch0[0] = _mm_adds_epi16(tmp0,tmp1); + ch1[0] = _mm_subs_epi16(tmp0,tmp1); + } + else { //ch0+j*ch1 ch0-j*ch1 tmp0 = ch0[0]; tmp1 = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); tmp1 = _mm_shufflelo_epi16(tmp1,_MM_SHUFFLE(2,3,0,1)); tmp1 = _mm_shufflehi_epi16(tmp1,_MM_SHUFFLE(2,3,0,1)); - ch0[0] = _mm_adds_epi16(tmp0,tmp1); - ch1[0] = _mm_subs_epi16(tmp0,tmp1); + ch0[0] = _mm_subs_epi16(tmp0,tmp1); + ch1[0] = _mm_add_epi16(tmp0,tmp1); } + //print_shorts("prec2A_TM4 ch0 (middle):",ch0); + //print_shorts("prec2A_TM4 ch1 (middle):",ch1); + ch0[0] = _mm_mulhi_epi16(ch0[0],amp); ch0[0] = _mm_slli_epi16(ch0[0],1); ch1[0] = _mm_mulhi_epi16(ch1[0],amp); ch1[0] = _mm_slli_epi16(ch1[0],1); -} - -#elif defined(__arm__) - -void prec2A_TM4_128(int pmi,int16x8_t *ch0,int16x8_t *ch1) -{ - int16x8_t amp; - int16x8_t tmp0,tmp1; - int16_t conj[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; - - amp = vmovq_n_s16(ONE_OVER_SQRT2_Q15); - - if (pmi == 0) { - ch0[0] = vqaddq_s16(ch0[0],ch1[0]); - ch1[0] = vqsubq_s16(ch0[0],ch1[0]); - } else { - tmp0 = ch0[0]; - tmp1 = vrev32q_s16(vmulq_s16(ch1[0],*(int16x8_t*)conj)); - ch0[0] = vqaddq_s16(tmp0,tmp1); - ch1[0] = vqsubq_s16(tmp0,tmp1); - } - ch0[0] = vqdmulhq_s16(ch0[0],amp); - ch1[0] = vqdmulhq_s16(ch1[0],amp); + // ch0[0] = _mm_srai_epi16(ch0[0],1); //divide by 2 + // ch1[0] = _mm_srai_epi16(ch1[0],1); //divide by 2 + //print_shorts("prec2A_TM4 ch0 (end):",ch0); + //print_shorts("prec2A_TM4 ch1 (end):",ch1); + _mm_empty(); + _m_empty(); + // print_shorts("prec2A_TM4 ch0 (end):",ch0); + //print_shorts("prec2A_TM4 ch1 (end):",ch1); } -#endif void dlsch_channel_compensation_TM56(int **rxdataF_ext, int **dl_ch_estimates_ext, @@ -1521,7 +1765,7 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, int **rxdataF_comp, unsigned char *pmi_ext, LTE_DL_FRAME_PARMS *frame_parms, - PHY_MEASUREMENTS *phy_measurements, + PHY_MEASUREMENTS *measurements, int eNB_id, unsigned char symbol, unsigned char mod_order, @@ -1575,6 +1819,7 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { + prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128[2],&dl_ch1_128[2]); } @@ -1594,6 +1839,9 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); + + //print_shorts("dl_ch_mag128[0]=",&dl_ch_mag128[0]); + //print_shorts("dl_ch_mag128[0]=",&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); @@ -1625,32 +1873,34 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, if (pilots==0) { dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); + } } // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],rxdataF128[0]); - // print_ints("re",&mmtmpD0); + // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); - // print_ints("im",&mmtmpD1); + + // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - // print_ints("re(shift)",&mmtmpD0); + // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); - // print_ints("im(shift)",&mmtmpD1); + // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); - // print_ints("c1",&mmtmpD3); + // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128); - // print_shorts("ch:",dl_ch128); - // print_shorts("pack:",rxdataF_comp128); + // print_shorts("rx:",rxdataF128); + // print_shorts("ch:",dl_ch128); + // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[1],rxdataF128[1]); @@ -1708,57 +1958,54 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, Nre = (pilots==0) ? 12 : 8; precoded_signal_strength += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (phy_measurements->n0_power[aarx])); + (nb_rb*Nre))) - (measurements->n0_power[aarx])); } // rx_antennas - phy_measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,phy_measurements->n0_power_tot); + measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,measurements->n0_power_tot); //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, - // phy_measurements->precoded_cqi_dB[eNB_id][0]); - - _mm_empty(); - _m_empty(); + // measurements->precoded_cqi_dB[eNB_id][0]); #elif defined(__arm__) uint32_t rb,Nre; uint32_t aarx,symbol_mod,pilots=0; - + int16x4_t *dl_ch0_128,*dl_ch1_128,*rxdataF128; int16x8_t *dl_ch0_128b,*dl_ch1_128b; int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,mmtmpD1b; int16x8_t *dl_ch_mag128,*dl_ch_mag128b,mmtmpD2,mmtmpD3,mmtmpD4,*rxdataF_comp128; int16x8_t QAM_amp128,QAM_amp128b; - + int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); int32_t precoded_signal_strength=0; - - symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : 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==1) // 10 out of 12 so don't reduce size { nb_rb=1+(5*nb_rb/6); } - + else { pilots=1; } } - - + + if (mod_order == 4) { QAM_amp128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = vmovq_n_s16(0); - + } else if (mod_order == 6) { QAM_amp128 = vmovq_n_s16(QAM64_n1); // QAM_amp128b = vmovq_n_s16(QAM64_n2); } - + // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); - + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { - - - + + + dl_ch0_128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch0_128b = (int16x8_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; @@ -1767,144 +2014,153 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, dl_ch_mag128b = (int16x8_t*)&dl_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (int16x8_t*)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12]; - + for (rb=0; rb<nb_rb; rb++) { #ifdef DEBUG_DLSCH_DEMOD printf("mode 6 prec: rb %d, pmi->%d\n",rb,pmi_ext[rb]); #endif prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[0],&dl_ch1_128b[0]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[1],&dl_ch1_128b[1]); - + if (pilots==0) { - prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[2],&dl_ch1_128b[2]); + prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[2],&dl_ch1_128b[2]); } - + if (mod_order>2) { - // get channel amplitude if not QPSK - mmtmpD0 = vmull_s16(dl_ch0_128[0], dl_ch0_128[0]); - // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits - mmtmpD1 = vmull_s16(dl_ch0_128[1], dl_ch0_128[1]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits - mmtmpD0 = vmull_s16(dl_ch0_128[2], dl_ch0_128[2]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch0_128[3], dl_ch0_128[3]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch0_128[4], dl_ch0_128[4]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch0_128[5], dl_ch0_128[5]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - - } - - dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); - dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); - dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); - dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); - - - if (pilots==0) { - dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); - dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); - } + // get channel amplitude if not QPSK + mmtmpD0 = vmull_s16(dl_ch0_128[0], dl_ch0_128[0]); + // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits + mmtmpD1 = vmull_s16(dl_ch0_128[1], dl_ch0_128[1]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits + mmtmpD0 = vmull_s16(dl_ch0_128[2], dl_ch0_128[2]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch0_128[3], dl_ch0_128[3]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + if (pilots==0) { + mmtmpD0 = vmull_s16(dl_ch0_128[4], dl_ch0_128[4]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch0_128[5], dl_ch0_128[5]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + + } + + dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); + dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); + dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); + dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); + + + if (pilots==0) { + dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); + dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); + } } mmtmpD0 = vmull_s16(dl_ch0_128[0], rxdataF128[0]); - //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] + //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] mmtmpD1 = vmull_s16(dl_ch0_128[1], rxdataF128[1]); - //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] + //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] - + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[0],*(int16x4_t*)conj)), rxdataF128[0]); //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] - + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[0] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - + mmtmpD0 = vmull_s16(dl_ch0_128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch0_128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[1] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - + if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch0_128[4], rxdataF128[4]); - mmtmpD1 = vmull_s16(dl_ch0_128[5], rxdataF128[5]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[4],*(int16x4_t*)conj)), rxdataF128[4]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[5],*(int16x4_t*)conj)), rxdataF128[5]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - - dl_ch0_128+=6; - dl_ch1_128+=6; - dl_ch_mag128+=3; - dl_ch_mag128b+=3; - rxdataF128+=6; - rxdataF_comp128+=3; - + mmtmpD0 = vmull_s16(dl_ch0_128[4], rxdataF128[4]); + mmtmpD1 = vmull_s16(dl_ch0_128[5], rxdataF128[5]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[4],*(int16x4_t*)conj)), rxdataF128[4]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[5],*(int16x4_t*)conj)), rxdataF128[5]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + + dl_ch0_128+=6; + dl_ch1_128+=6; + dl_ch_mag128+=3; + dl_ch_mag128b+=3; + rxdataF128+=6; + rxdataF_comp128+=3; + } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less - dl_ch0_128+=4; - dl_ch1_128+=4; - dl_ch_mag128+=2; - dl_ch_mag128b+=2; - rxdataF128+=4; - rxdataF_comp128+=2; + dl_ch0_128+=4; + dl_ch1_128+=4; + dl_ch_mag128+=2; + dl_ch_mag128b+=2; + rxdataF128+=4; + rxdataF_comp128+=2; } } - + Nre = (pilots==0) ? 12 : 8; - + + precoded_signal_strength += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (phy_measurements->n0_power[aarx])); + + (nb_rb*Nre))) - (measurements->n0_power[aarx])); // rx_antennas } - phy_measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,phy_measurements->n0_power_tot); - + measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,measurements->n0_power_tot); + + //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, + // measurements->precoded_cqi_dB[eNB_id][0]); + #endif + _mm_empty(); + _m_empty(); } -void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, +void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_PDSCH *pdsch_vars, PHY_MEASUREMENTS *measurements, int eNB_id, unsigned char symbol, unsigned char mod_order0, unsigned char mod_order1, + int harq_pid, int round, + MIMO_mode_t mimo_mode, unsigned short nb_rb, - unsigned char output_shift) -{ + unsigned char output_shift0, + unsigned char output_shift1) { #if defined(__x86_64__) || defined(__i386__) @@ -1912,25 +2168,27 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, __m128i *dl_ch0_128,*dl_ch1_128,*dl_ch_mag0_128,*dl_ch_mag1_128,*dl_ch_mag0_128b,*dl_ch_mag1_128b,*rxdataF128,*rxdataF_comp0_128,*rxdataF_comp1_128; unsigned char aarx=0,symbol_mod,pilots=0; int precoded_signal_strength0=0,precoded_signal_strength1=0; + int rx_power_correction; int **rxdataF_ext = pdsch_vars->rxdataF_ext; int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; - int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1; + int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1[harq_pid][round]; int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; - int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1; + int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1[harq_pid][round]; int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; - int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[round]; //? + int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; + unsigned char *pmi_ext = pdsch_vars->pmi_ext; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128,QAM_amp0_128b,QAM_amp1_128,QAM_amp1_128b; - symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) pilots=1; + rx_power_correction = 1; - //printf("comp prec: symbol %d, pilots %d\n",symbol, pilots); + // printf("comp prec: symbol %d, pilots %d\n",symbol, pilots); if (mod_order0 == 4) { QAM_amp0_128 = _mm_set1_epi16(QAM16_n1); @@ -1948,39 +2206,83 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, QAM_amp1_128b = _mm_set1_epi16(QAM64_n2); } - for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { + + /* if (aarx==0) { + output_shift=output_shift0; + } + else { + output_shift=output_shift1; + } */ - dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // hr,0 - dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; // hr,1 + // printf("antenna %d\n", aarx); + // printf("symbol %d, rx antenna %d\n", symbol, aarx); + dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // this is h11 + dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; // this is h12 - dl_ch_mag0_128 = (__m128i *)&dl_ch_mag0[aarx][symbol*frame_parms->N_RB_DL*12]; - dl_ch_mag0_128b = (__m128i *)&dl_ch_magb0[aarx][symbol*frame_parms->N_RB_DL*12]; - dl_ch_mag1_128 = (__m128i *)&dl_ch_mag1[aarx][symbol*frame_parms->N_RB_DL*12]; - dl_ch_mag1_128b = (__m128i *)&dl_ch_magb1[aarx][symbol*frame_parms->N_RB_DL*12]; - rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // yr - rxdataF_comp0_128 = (__m128i *)&rxdataF_comp0[aarx][symbol*frame_parms->N_RB_DL*12]; // yr,0 = yr * conj(hr,0) - rxdataF_comp1_128 = (__m128i *)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; // yr,1 = yr * conj(hr,1) + dl_ch_mag0_128 = (__m128i *)&dl_ch_mag0[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x1 + dl_ch_mag0_128b = (__m128i *)&dl_ch_magb0[aarx][symbol*frame_parms->N_RB_DL*12];//responsible for x1 + dl_ch_mag1_128 = (__m128i *)&dl_ch_mag1[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x2. always coming from tx2 + dl_ch_mag1_128b = (__m128i *)&dl_ch_magb1[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x2. always coming from tx2 + rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; //received signal on antenna of interest h11*x1+h12*x2 + rxdataF_comp0_128 = (__m128i *)&rxdataF_comp0[aarx][symbol*frame_parms->N_RB_DL*12]; //result of multipl with MF x1 on antenna of interest + rxdataF_comp1_128 = (__m128i *)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; //result of multipl with MF x2 on antenna of interest for (rb=0; rb<nb_rb; rb++) { + // combine TX channels using precoder from pmi + if (mimo_mode==LARGE_CDD) { + prec2A_TM3_128(&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM3_128(&dl_ch0_128[1],&dl_ch1_128[1]); - prec2A_TM3_128(&dl_ch0_128[0],&dl_ch1_128[0]); - prec2A_TM3_128(&dl_ch0_128[1],&dl_ch1_128[1]); - if (pilots==0) { - prec2A_TM3_128(&dl_ch0_128[2],&dl_ch1_128[2]); + if (pilots==0) { + prec2A_TM3_128(&dl_ch0_128[2],&dl_ch1_128[2]); + } + } + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) { + prec2A_TM4_128(0,&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM4_128(0,&dl_ch0_128[1],&dl_ch1_128[1]); + + if (pilots==0) { + prec2A_TM4_128(0,&dl_ch0_128[2],&dl_ch1_128[2]); + } + } + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) { + prec2A_TM4_128(1,&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM4_128(1,&dl_ch0_128[1],&dl_ch1_128[1]); + + if (pilots==0) { + prec2A_TM4_128(1,&dl_ch0_128[2],&dl_ch1_128[2]); + } + } + + else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) { + prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[1],&dl_ch1_128[1]); + + if (pilots==0) { + prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[2],&dl_ch1_128[2]); + } + } + + + else { + LOG_E(PHY,"Unknown MIMO mode\n"); + return; } + if (mod_order0>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],dl_ch0_128[0]); - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); mmtmpD1 = _mm_madd_epi16(dl_ch0_128[1],dl_ch0_128[1]); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); @@ -1991,6 +2293,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, // print_shorts("dl_ch_mag0_128[0]=",&dl_ch_mag0_128[0]); + dl_ch_mag0_128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag0_128b[1] = dl_ch_mag0_128[1]; dl_ch_mag0_128[1] = _mm_mulhi_epi16(dl_ch_mag0_128[1],QAM_amp0_128); @@ -1998,7 +2301,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch0_128[2],dl_ch0_128[2]); - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); @@ -2012,7 +2315,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, dl_ch_mag0_128b[0] = _mm_mulhi_epi16(dl_ch_mag0_128b[0],QAM_amp0_128b); dl_ch_mag0_128b[0] = _mm_slli_epi16(dl_ch_mag0_128b[0],1); - //print_shorts("dl_ch_mag128b[0]=",&dl_ch_mag128b[0]); + // print_shorts("dl_ch_mag0_128b[0]=",&dl_ch_mag0_128b[0]); dl_ch_mag0_128b[1] = _mm_mulhi_epi16(dl_ch_mag0_128b[1],QAM_amp0_128b); dl_ch_mag0_128b[1] = _mm_slli_epi16(dl_ch_mag0_128b[1],1); @@ -2027,10 +2330,10 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch1_128[0],dl_ch1_128[0]); - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); mmtmpD1 = _mm_madd_epi16(dl_ch1_128[1],dl_ch1_128[1]); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); @@ -2039,7 +2342,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, dl_ch_mag1_128[0] = _mm_mulhi_epi16(dl_ch_mag1_128[0],QAM_amp1_128); dl_ch_mag1_128[0] = _mm_slli_epi16(dl_ch_mag1_128[0],1); - //print_shorts("dl_ch_mag128[0]=",&dl_ch_mag128[0]); + // print_shorts("dl_ch_mag1_128[0]=",&dl_ch_mag1_128[0]); dl_ch_mag1_128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag1_128b[1] = dl_ch_mag1_128[1]; @@ -2048,7 +2351,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch1_128[2],dl_ch1_128[2]); - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); @@ -2062,7 +2365,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, dl_ch_mag1_128b[0] = _mm_mulhi_epi16(dl_ch_mag1_128b[0],QAM_amp1_128b); dl_ch_mag1_128b[0] = _mm_slli_epi16(dl_ch_mag1_128b[0],1); - //print_shorts("dl_ch_mag128b[0]=",&dl_ch_mag128b[0]); + // print_shorts("dl_ch_mag1_128b[0]=",&dl_ch_mag1_128b[0]); dl_ch_mag1_128b[1] = _mm_mulhi_epi16(dl_ch_mag1_128b[1],QAM_amp1_128b); dl_ch_mag1_128b[1] = _mm_slli_epi16(dl_ch_mag1_128b[1],1); @@ -2076,28 +2379,29 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, // layer 0 // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],rxdataF128[0]); - //print_ints("re",&mmtmpD0); + // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); - // print_ints("im",&mmtmpD1); + // print_ints("im",&mmtmpD1); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - // printf("Shift: %d\n",output_shift); - // print_ints("re(shift)",&mmtmpD0); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); - // print_ints("im(shift)",&mmtmpD1); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); + // printf("Shift: %d\n",output_shift); + // print_ints("re(shift)",&mmtmpD0); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); + // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - // print_ints("c0",&mmtmpD2); - // print_ints("c1",&mmtmpD3); + // print_ints("c0",&mmtmpD2); + // print_ints("c1",&mmtmpD3); rxdataF_comp0_128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128); - // print_shorts("ch:",dl_ch0_128); - // print_shorts("pack:",rxdataF_comp0_128); + + // print_shorts("rx:",rxdataF128); + // print_shorts("ch:",dl_ch0_128); + // print_shorts("pack:",rxdataF_comp0_128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[1],rxdataF128[1]); @@ -2107,15 +2411,15 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp0_128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128+1); - // print_shorts("ch:",dl_ch0_128+1); - // print_shorts("pack:",rxdataF_comp128+1); + // print_shorts("rx:",rxdataF128+1); + // print_shorts("ch:",dl_ch0_128+1); + // print_shorts("pack:",rxdataF_comp0_128+1); if (pilots==0) { // multiply by conjugated channel @@ -2126,17 +2430,15 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp0_128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128+2); - // print_shorts("ch:",dl_ch0_128+2); - // print_shorts("pack:",rxdataF_comp128+2); - - } else { + // print_shorts("rx:",rxdataF128+2); + // print_shorts("ch:",dl_ch0_128+2); + // print_shorts("pack:",rxdataF_comp0_128+2); } @@ -2144,29 +2446,29 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, // layer 1 // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch1_128[0],rxdataF128[0]); - // print_ints("re",&mmtmpD0); + // print_ints("re",&mmtmpD0); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch1_128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); - // print_ints("im",&mmtmpD1); + // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - // print_ints("re(shift)",&mmtmpD0); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); - // print_ints("im(shift)",&mmtmpD1); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); + // print_ints("re(shift)",&mmtmpD0); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); + // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - // print_ints("c0",&mmtmpD2); - // print_ints("c1",&mmtmpD3); + // print_ints("c0",&mmtmpD2); + // print_ints("c1",&mmtmpD3); rxdataF_comp1_128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128); - // print_shorts("ch:",dl_ch128); - // print_shorts("pack:",rxdataF_comp128); + // print_shorts("rx:",rxdataF128); + // print_shorts("ch:",dl_ch1_128); + // print_shorts("pack:",rxdataF_comp1_128); - // multiply by conjugated channel + // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch1_128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch1_128[1],_MM_SHUFFLE(2,3,0,1)); @@ -2174,15 +2476,15 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp1_128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128+1); - // print_shorts("ch:",dl_ch128+1); - // print_shorts("pack:",rxdataF_comp128+1); + // print_shorts("rx:",rxdataF128+1); + // print_shorts("ch:",dl_ch1_128+1); + // print_shorts("pack:",rxdataF_comp1_128+1); if (pilots==0) { // multiply by conjugated channel @@ -2193,15 +2495,15 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp1_128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128+2); - // print_shorts("ch:",dl_ch128+2); - // print_shorts("pack:",rxdataF_comp128+2); + // print_shorts("rx:",rxdataF128+2); + // print_shorts("ch:",dl_ch1_128+2); + // print_shorts("pack:",rxdataF_comp1_128+2); dl_ch0_128+=3; dl_ch1_128+=3; @@ -2212,7 +2514,8 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, rxdataF128+=3; rxdataF_comp0_128+=3; rxdataF_comp1_128+=3; - } else { + } + else { dl_ch0_128+=2; dl_ch1_128+=2; dl_ch_mag0_128+=2; @@ -2225,85 +2528,85 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, } } // rb loop - } - - Nre = (pilots==0) ? 12 : 8; + Nre = (pilots==0) ? 12 : 8; - precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (measurements->n0_power[aarx])); + precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], + (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); - precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (measurements->n0_power[aarx])); + precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], + (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); + } // rx_antennas measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,measurements->n0_power_tot); measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,measurements->n0_power_tot); - //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, - // measurements->precoded_cqi_dB[eNB_id][0]); + // printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, + // measurements->precoded_cqi_dB[eNB_id][0]); _mm_empty(); _m_empty(); -#elif defined(__arm__) + #elif defined(__arm__) unsigned short rb,Nre; unsigned char aarx,symbol_mod,pilots=0; - int precoded_signal_strength0=0,precoded_signal_strength1=0; + int precoded_signal_strength0=0,precoded_signal_strength1=0, rx_power_correction; int16x4_t *dl_ch0_128,*rxdataF128; int16x4_t *dl_ch1_128; int16x8_t *dl_ch0_128b,*dl_ch1_128b; - + int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,mmtmpD1b; int16x8_t *dl_ch_mag0_128,*dl_ch_mag0_128b,*dl_ch_mag1_128,*dl_ch_mag1_128b,mmtmpD2,mmtmpD3,mmtmpD4,*rxdataF_comp0_128,*rxdataF_comp1_128; int16x8_t QAM_amp0_128,QAM_amp0_128b,QAM_amp1_128,QAM_amp1_128b; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); - + int **rxdataF_ext = pdsch_vars->rxdataF_ext; int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; - int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1; + int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1[harq_pid][round]; int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; - int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1; + int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1[harq_pid][round]; int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; - int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[round]; //? - + int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; + int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; - + 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==1) // 10 out of 12 so don't reduce size { nb_rb=1+(5*nb_rb/6); } - + else { pilots=1; } } - - + + rx_power_correction=1; + if (mod_order0 == 4) { QAM_amp0_128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp0_128b = vmovq_n_s16(0); - + } else if (mod_order0 == 6) { QAM_amp0_128 = vmovq_n_s16(QAM64_n1); // QAM_amp0_128b = vmovq_n_s16(QAM64_n2); } - + if (mod_order1 == 4) { QAM_amp1_128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp1_128b = vmovq_n_s16(0); - + } else if (mod_order1 == 6) { QAM_amp1_128 = vmovq_n_s16(QAM64_n1); // QAM_amp1_128b = vmovq_n_s16(QAM64_n2); } - + // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); - + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { - - - + + + dl_ch0_128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch0_128b = (int16x8_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; @@ -2315,195 +2618,215 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp0_128 = (int16x8_t*)&rxdataF_comp0[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp1_128 = (int16x8_t*)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; - + for (rb=0; rb<nb_rb; rb++) { -#ifdef DEBUG_DLSCH_DEMOD - printf("mode 6 prec: rb %d, pmi->%d\n",rb,pmi_ext[rb]); -#endif + // combine TX channels using precoder from pmi + if (mimo_mode==LARGE_CDD) { + prec2A_TM3_128(&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM3_128(&dl_ch0_128[1],&dl_ch1_128[1]); - prec2A_TM3_128(&dl_ch0_128b[0],&dl_ch1_128b[0]); - prec2A_TM3_128(&dl_ch0_128b[1],&dl_ch1_128b[1]); - - if (pilots==0) { - prec2A_TM3_128(&dl_ch0_128b[2],&dl_ch1_128b[2]); + + if (pilots==0) { + prec2A_TM3_128(&dl_ch0_128[2],&dl_ch1_128[2]); + } + } + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) { + prec2A_TM4_128(0,&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM4_128(0,&dl_ch0_128[1],&dl_ch1_128[1]); + + if (pilots==0) { + prec2A_TM4_128(0,&dl_ch0_128[2],&dl_ch1_128[2]); + } } + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) { + prec2A_TM4_128(1,&dl_ch0_128[0],&dl_ch1_128[0]); + prec2A_TM4_128(1,&dl_ch0_128[1],&dl_ch1_128[1]); + + if (pilots==0) { + prec2A_TM4_128(1,&dl_ch0_128[2],&dl_ch1_128[2]); + } + } + else { + LOG_E(PHY,"Unknown MIMO mode\n"); + return; + } + - if (mod_order0>2) { - // get channel amplitude if not QPSK - mmtmpD0 = vmull_s16(dl_ch0_128[0], dl_ch0_128[0]); - // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits - mmtmpD1 = vmull_s16(dl_ch0_128[1], dl_ch0_128[1]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits - mmtmpD0 = vmull_s16(dl_ch0_128[2], dl_ch0_128[2]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch0_128[3], dl_ch0_128[3]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch0_128[4], dl_ch0_128[4]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch0_128[5], dl_ch0_128[5]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - - } - - dl_ch_mag0_128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp0_128b); - dl_ch_mag0_128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp0_128b); - dl_ch_mag0_128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp0_128); - dl_ch_mag0_128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp0_128); - - - if (pilots==0) { - dl_ch_mag0_128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp0_128b); - dl_ch_mag0_128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp0_128); - } + // get channel amplitude if not QPSK + mmtmpD0 = vmull_s16(dl_ch0_128[0], dl_ch0_128[0]); + // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits + mmtmpD1 = vmull_s16(dl_ch0_128[1], dl_ch0_128[1]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits + mmtmpD0 = vmull_s16(dl_ch0_128[2], dl_ch0_128[2]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch0_128[3], dl_ch0_128[3]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + if (pilots==0) { + mmtmpD0 = vmull_s16(dl_ch0_128[4], dl_ch0_128[4]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch0_128[5], dl_ch0_128[5]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + + } + + dl_ch_mag0_128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp0_128b); + dl_ch_mag0_128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp0_128b); + dl_ch_mag0_128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp0_128); + dl_ch_mag0_128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp0_128); + + + if (pilots==0) { + dl_ch_mag0_128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp0_128b); + dl_ch_mag0_128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp0_128); + } } if (mod_order1>2) { - // get channel amplitude if not QPSK - mmtmpD0 = vmull_s16(dl_ch1_128[0], dl_ch1_128[0]); - // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits - mmtmpD1 = vmull_s16(dl_ch1_128[1], dl_ch1_128[1]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits - mmtmpD0 = vmull_s16(dl_ch1_128[2], dl_ch1_128[2]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch1_128[3], dl_ch1_128[3]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch1_128[4], dl_ch1_128[4]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch1_128[5], dl_ch1_128[5]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - - - } - - dl_ch_mag1_128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp1_128b); - dl_ch_mag1_128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp1_128b); - dl_ch_mag1_128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp1_128); - dl_ch_mag1_128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp1_128); - - - if (pilots==0) { - dl_ch_mag1_128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp1_128b); - dl_ch_mag1_128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp1_128); - } + // get channel amplitude if not QPSK + mmtmpD0 = vmull_s16(dl_ch1_128[0], dl_ch1_128[0]); + // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits + mmtmpD1 = vmull_s16(dl_ch1_128[1], dl_ch1_128[1]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits + mmtmpD0 = vmull_s16(dl_ch1_128[2], dl_ch1_128[2]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch1_128[3], dl_ch1_128[3]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + if (pilots==0) { + mmtmpD0 = vmull_s16(dl_ch1_128[4], dl_ch1_128[4]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch1_128[5], dl_ch1_128[5]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + + + } + + dl_ch_mag1_128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp1_128b); + dl_ch_mag1_128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp1_128b); + dl_ch_mag1_128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp1_128); + dl_ch_mag1_128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp1_128); + + + if (pilots==0) { + dl_ch_mag1_128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp1_128b); + dl_ch_mag1_128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp1_128); + } } - + mmtmpD0 = vmull_s16(dl_ch0_128[0], rxdataF128[0]); - //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] + //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] mmtmpD1 = vmull_s16(dl_ch0_128[1], rxdataF128[1]); - //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] + //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] - + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[0],*(int16x4_t*)conj)), rxdataF128[0]); //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] - + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp0_128[0] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - + mmtmpD0 = vmull_s16(dl_ch0_128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch0_128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp0_128[1] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - + // second stream mmtmpD0 = vmull_s16(dl_ch1_128[0], rxdataF128[0]); mmtmpD1 = vmull_s16(dl_ch1_128[1], rxdataF128[1]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[0],*(int16x4_t*)conj)), rxdataF128[0]); - + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] - + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp1_128[0] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - + mmtmpD0 = vmull_s16(dl_ch1_128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch1_128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp1_128[1] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - + if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch0_128[4], rxdataF128[4]); - mmtmpD1 = vmull_s16(dl_ch0_128[5], rxdataF128[5]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[4],*(int16x4_t*)conj)), rxdataF128[4]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[5],*(int16x4_t*)conj)), rxdataF128[5]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp0_128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - mmtmpD0 = vmull_s16(dl_ch1_128[4], rxdataF128[4]); - mmtmpD1 = vmull_s16(dl_ch1_128[5], rxdataF128[5]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch1_128[4],*(int16x4_t*)conj)), rxdataF128[4]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch1_128[5],*(int16x4_t*)conj)), rxdataF128[5]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - - - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp1_128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + mmtmpD0 = vmull_s16(dl_ch0_128[4], rxdataF128[4]); + mmtmpD1 = vmull_s16(dl_ch0_128[5], rxdataF128[5]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[4],*(int16x4_t*)conj)), rxdataF128[4]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[5],*(int16x4_t*)conj)), rxdataF128[5]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp0_128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + mmtmpD0 = vmull_s16(dl_ch1_128[4], rxdataF128[4]); + mmtmpD1 = vmull_s16(dl_ch1_128[5], rxdataF128[5]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch1_128[4],*(int16x4_t*)conj)), rxdataF128[4]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch1_128[5],*(int16x4_t*)conj)), rxdataF128[5]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + + + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp1_128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); } } - - - + + + Nre = (pilots==0) ? 12 : 8; // rx_antennas @@ -2513,11 +2836,9 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, Nre = (pilots==0) ? 12 : 8; precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (measurements->n0_power[aarx])); - + (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (measurements->n0_power[aarx])); - + (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,measurements->n0_power_tot); measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,measurements->n0_power_tot); @@ -2525,6 +2846,7 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, #endif } + void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, unsigned char symbol, unsigned short nb_rb, @@ -2552,6 +2874,9 @@ void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + + + //printf ("antenna %d", aarx); dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; if (dl_ch_estimates_ext_i == NULL) // TM3/4 @@ -2582,7 +2907,128 @@ void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); dl_ch_rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); + // print_shorts("rho 0:",dl_ch_rho128); + // multiply by conjugated channel + mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); + mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[1]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); + mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); + dl_ch_rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); + + + if (pilots==0) { + + // multiply by conjugated channel + mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); + mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[2]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); + mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); + dl_ch_rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); + + dl_ch128+=3; + dl_ch128i+=3; + dl_ch_rho128+=3; + } else { + + dl_ch128+=2; + dl_ch128i+=2; + dl_ch_rho128+=2; + } + } + + } + + _mm_empty(); + _m_empty(); + +#elif defined(__arm__) + +#endif +} + + +/*void dlsch_dual_stream_correlationTM34(LTE_DL_FRAME_PARMS *frame_parms, + unsigned char symbol, + unsigned short nb_rb, + int **dl_ch_estimates_ext, + int **dl_ch_estimates_ext_i, + int **dl_ch_rho_ext, + unsigned char output_shift0, + unsigned char output_shift1) +{ + +#if defined(__x86_64__)||defined(__i386__) + + unsigned short rb; + __m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128,mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3; + unsigned char aarx,symbol_mod,pilots=0; + int output_shift; + // printf("dlsch_dual_stream_correlation: symbol %d\n",symbol); + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { + pilots=1; + } + + // printf("Dual stream correlation (%p)\n",dl_ch_estimates_ext_i); + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + + if (aarx==0) { + output_shift=output_shift0; + } + else { + output_shift=output_shift1; + } + + //printf ("antenna %d", aarx); + dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; + + if (dl_ch_estimates_ext_i == NULL) // TM3/4 + dl_ch128i = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; + else + 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]; + + + for (rb=0; rb<nb_rb; rb++) { + // multiply by conjugated channel + mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]); + // print_ints("re",&mmtmpD0); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); + mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); + mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[0]); + // print_ints("im",&mmtmpD1); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + // print_ints("re(shift)",&mmtmpD0); + mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); + // print_ints("im(shift)",&mmtmpD1); + mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); + mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); + // print_ints("c0",&mmtmpD2); + // print_ints("c1",&mmtmpD3); + dl_ch_rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); + // print_shorts("rho 0:",dl_ch_rho128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) @@ -2597,7 +3043,9 @@ void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); dl_ch_rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); + if (pilots==0) { + // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) @@ -2612,15 +3060,17 @@ void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); dl_ch_rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - dl_ch128+=3; + dl_ch128+=3; dl_ch128i+=3; dl_ch_rho128+=3; } else { + dl_ch128+=2; dl_ch128i+=2; dl_ch_rho128+=2; } } + } _mm_empty(); @@ -2630,6 +3080,7 @@ void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, #endif } +*/ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, @@ -2664,20 +3115,24 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, dl_ch_mag128_1b = (__m128i *)&dl_ch_magb[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) - for (i=0; i<nb_rb*3; i++) { + for (i=0;i<nb_rb*3;i++) { rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1)); dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1)); + // print_shorts("mrc comp0:",&rxdataF_comp128_0[i]); + // print_shorts("mrc mag0:",&dl_ch_mag128_0[i]); + // print_shorts("mrc mag0b:",&dl_ch_mag128_0b[i]); + // print_shorts("mrc rho1:",&rho128_1[i]); + } } if (rho) { rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; - - for (i=0; i<nb_rb*3; i++) { - // print_shorts("mrc rho0:",&rho128_0[i]); - // print_shorts("mrc rho1:",&rho128_1[i]); + for (i=0;i<nb_rb*3;i++) { + // print_shorts("mrc rho0:",&rho128_0[i]); + // print_shorts("mrc rho1:",&rho128_1[i]); rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); } } @@ -2767,9 +3222,90 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, #endif } + +void dlsch_detection_mrc_TM34(LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDSCH *pdsch_vars, + int harq_pid, + int round, + unsigned char symbol, + unsigned short nb_rb, + unsigned char dual_stream_UE) { + + int i; + __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1,*dl_ch_mag128_i0,*dl_ch_mag128_i1,*dl_ch_mag128_i0b,*dl_ch_mag128_i1b; + + int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; + int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; + int **dl_ch_rho_ext = pdsch_vars->dl_ch_rho_ext[harq_pid][round]; //for second stream + int **dl_ch_rho2_ext = pdsch_vars->dl_ch_rho2_ext; + int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; + int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1[harq_pid][round]; + int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; + int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1[harq_pid][round]; + + if (frame_parms->nb_antennas_rx>1) { + + rxdataF_comp128_0 = (__m128i *)&rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_1 = (__m128i *)&rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_0 = (__m128i *)&dl_ch_mag0[0][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_1 = (__m128i *)&dl_ch_mag0[1][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_0b = (__m128i *)&dl_ch_magb0[0][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_1b = (__m128i *)&dl_ch_magb0[1][symbol*frame_parms->N_RB_DL*12]; + + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) + for (i=0;i<nb_rb*3;i++) { + rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); + dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1)); + dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1)); + + // print_shorts("mrc compens0:",&rxdataF_comp128_0[i]); + // print_shorts("mrc mag128_0:",&dl_ch_mag128_0[i]); + // print_shorts("mrc mag128_0b:",&dl_ch_mag128_0b[i]); + } } + + // if (rho) { + rho128_0 = (__m128i *) &dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12]; + rho128_1 = (__m128i *) &dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12]; + for (i=0;i<nb_rb*3;i++) { + // print_shorts("mrc rho0:",&rho128_0[i]); + // print_shorts("mrc rho1:",&rho128_1[i]); + rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); + } + //} + + + if (dual_stream_UE == 1) { + rho128_i0 = (__m128i *) &dl_ch_rho_ext[0][symbol*frame_parms->N_RB_DL*12]; + rho128_i1 = (__m128i *) &dl_ch_rho_ext[1][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp1[0][symbol*frame_parms->N_RB_DL*12]; + rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp1[1][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_i0 = (__m128i *)&dl_ch_mag1[0][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_i1 = (__m128i *)&dl_ch_mag1[1][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_i0b = (__m128i *)&dl_ch_magb1[0][symbol*frame_parms->N_RB_DL*12]; + dl_ch_mag128_i1b = (__m128i *)&dl_ch_magb1[1][symbol*frame_parms->N_RB_DL*12]; + for (i=0;i<nb_rb*3;i++) { + 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)); + + dl_ch_mag128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0[i],1),_mm_srai_epi16(dl_ch_mag128_i1[i],1)); + dl_ch_mag128_i0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0b[i],1),_mm_srai_epi16(dl_ch_mag128_i1b[i],1)); + + //print_shorts("mrc compens1:",&rxdataF_comp128_i0[i]); + //print_shorts("mrc mag128_i0:",&dl_ch_mag128_i0[i]); + //print_shorts("mrc mag128_i0b:",&dl_ch_mag128_i0b[i]); + } + } + + + _mm_empty(); + _m_empty(); +} + + + void dlsch_scale_channel(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, - LTE_UE_DLSCH_t **dlsch, + LTE_UE_DLSCH_t **dlsch_ue, uint8_t symbol, unsigned short nb_rb) { @@ -2790,9 +3326,11 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext, } // Determine scaling amplitude based the symbol - ch_amp = ((pilots) ? (dlsch[0]->sqrt_rho_b) : (dlsch[0]->sqrt_rho_a)); - // LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); +ch_amp = ((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); + + LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n",symbol_mod,ch_amp,pilots,nb_rb,frame_parms->Ncp,symbol); + // printf("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13 @@ -2801,7 +3339,8 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext, dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; - for (rb=0; rb<nb_rb; rb++) { + for (rb=0;rb<nb_rb;rb++) { + dl_ch128[0] = _mm_mulhi_epi16(dl_ch128[0],ch_amp128); dl_ch128[0] = _mm_slli_epi16(dl_ch128[0],3); @@ -2814,6 +3353,7 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext, dl_ch128[2] = _mm_mulhi_epi16(dl_ch128[2],ch_amp128); dl_ch128[2] = _mm_slli_epi16(dl_ch128[2],3); dl_ch128+=3; + } } } @@ -2824,10 +3364,11 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext, #endif } + //compute average channel_level on each (TX,RX) antenna pair void dlsch_channel_level(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, - int *avg, + int32_t *avg, uint8_t symbol, unsigned short nb_rb) { @@ -2836,10 +3377,23 @@ void dlsch_channel_level(int **dl_ch_estimates_ext, short rb; unsigned char aatx,aarx,nre=12,symbol_mod; - __m128i *dl_ch128,avg128D; + __m128i *dl_ch128, avg128D, coeff128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) + nre=8; + else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) + nre=10; + else + nre=12; + + double one_over_nb_re = 0.0; + one_over_nb_re = 1/((double)(nb_rb*nre)); + int16_t one_over_nb_re_q1_15 = (int16_t)(one_over_nb_re * (double)(1<<15) ); + coeff128 = _mm_set_epi16(one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15, + one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15,one_over_nb_re_q1_15); + for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level @@ -2848,19 +3402,19 @@ void dlsch_channel_level(int **dl_ch_estimates_ext, dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; - for (rb=0; rb<nb_rb; rb++) { - // printf("rb %d : ",rb); - // print_shorts("ch",&dl_ch128[0]); - avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],dl_ch128[0])); - avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],dl_ch128[1])); + for (rb=0;rb<nb_rb;rb++) { + // printf("rb %d : ",rb); + // print_shorts("ch",&dl_ch128[0]); + avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[0], coeff128),15))); + avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[1], coeff128),15))); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { dl_ch128+=2; - } else { - avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],dl_ch128[2])); + } + else { + avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[2], coeff128),15))); dl_ch128+=3; } - /* if (rb==0) { print_shorts("dl_ch128",&dl_ch128[0]); @@ -2870,19 +3424,11 @@ void dlsch_channel_level(int **dl_ch_estimates_ext, */ } - if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) - nre=8; - else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) - nre=10; - else - nre=12; - - avg[(aatx<<1)+aarx] = (((int*)&avg128D)[0] + - ((int*)&avg128D)[1] + - ((int*)&avg128D)[2] + - ((int*)&avg128D)[3])/(nb_rb*nre); - - // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); + avg[(aatx<<1)+aarx] =(((int32_t*)&avg128D)[0] + + ((int32_t*)&avg128D)[1] + + ((int32_t*)&avg128D)[2] + + ((int32_t*)&avg128D)[3]); + // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); } _mm_empty(); @@ -2930,34 +3476,177 @@ void dlsch_channel_level(int **dl_ch_estimates_ext, */ } - if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) - nre=8; - else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) - nre=10; - else - nre=12; + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) + nre=8; + else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) + nre=10; + else + nre=12; + + avg[(aatx<<1)+aarx] = (((int32_t*)&avg128D)[0] + + ((int32_t*)&avg128D)[1] + + ((int32_t*)&avg128D)[2] + + ((int32_t*)&avg128D)[3])/(nb_rb*nre); + + // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); + } + + +#endif +} + +//compute average channel_level of effective (precoded) channel + +//compute average channel_level of effective (precoded) channel +void dlsch_channel_level_TM34(int **dl_ch_estimates_ext, + LTE_DL_FRAME_PARMS *frame_parms, + unsigned char *pmi_ext, + int *avg_0, + int *avg_1, + uint8_t symbol, + unsigned short nb_rb, + MIMO_mode_t mimo_mode){ + +#if defined(__x86_64__)||defined(__i386__) + + + short rb; + unsigned char aarx,nre=12,symbol_mod; + __m128i *dl_ch0_128,*dl_ch1_128, dl_ch0_128_tmp, dl_ch1_128_tmp, avg_0_128D, avg_1_128D; + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + //clear average level + // avg_0_128D = _mm_setzero_si128(); + // avg_1_128D = _mm_setzero_si128(); + avg_0[0] = 0; + avg_0[1] = 0; + avg_1[0] = 0; + avg_1[1] = 0; + // 5 is always a symbol with no pilots for both normal and extended prefix + + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) + nre=8; + else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) + nre=10; + else + nre=12; + + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; + dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; + + avg_0_128D = _mm_setzero_si128(); + avg_1_128D = _mm_setzero_si128(); + for (rb=0; rb<nb_rb; rb++) { + // printf("rb %d : \n",rb); + // print_shorts("ch0\n",&dl_ch0_128[0]); + //print_shorts("ch1\n",&dl_ch1_128[0]); + dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[0]); + dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[0]); + + if (mimo_mode==LARGE_CDD) + prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) + prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) + prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) + prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); + + // mmtmpD0 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); + avg_0_128D = _mm_add_epi32(avg_0_128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); + + avg_1_128D = _mm_add_epi32(avg_1_128D,_mm_madd_epi16(dl_ch1_128_tmp,dl_ch1_128_tmp)); + + dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[1]); + dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[1]); + + if (mimo_mode==LARGE_CDD) + prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) + prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) + prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) + prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); + + // mmtmpD1 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); + avg_0_128D = _mm_add_epi32(avg_0_128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); + + avg_1_128D = _mm_add_epi32(avg_1_128D,_mm_madd_epi16(dl_ch1_128_tmp,dl_ch1_128_tmp)); + + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { + dl_ch0_128+=2; + dl_ch1_128+=2; + } + else { + dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[2]); + dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[2]); + + if (mimo_mode==LARGE_CDD) + prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) + prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) + prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) + prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); + // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); + + avg_1_128D = _mm_add_epi32(avg_1_128D,_mm_madd_epi16(dl_ch1_128_tmp,dl_ch1_128_tmp)); + avg_0_128D = _mm_add_epi32(avg_0_128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); + + dl_ch0_128+=3; + dl_ch1_128+=3; + } + } + - avg[(aatx<<1)+aarx] = (((int32_t*)&avg128D)[0] + - ((int32_t*)&avg128D)[1] + - ((int32_t*)&avg128D)[2] + - ((int32_t*)&avg128D)[3])/(nb_rb*nre); - // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); - } + avg_0[aarx] = (((int*)&avg_0_128D)[0])/(nb_rb*nre) + + (((int*)&avg_0_128D)[1])/(nb_rb*nre) + + (((int*)&avg_0_128D)[2])/(nb_rb*nre) + + (((int*)&avg_0_128D)[3])/(nb_rb*nre); + // printf("From Chan_level aver stream 0 %d =%d\n", aarx, avg_0[aarx]); + + avg_1[aarx] = (((int*)&avg_1_128D)[0])/(nb_rb*nre) + + (((int*)&avg_1_128D)[1])/(nb_rb*nre) + + (((int*)&avg_1_128D)[2])/(nb_rb*nre) + + (((int*)&avg_1_128D)[3])/(nb_rb*nre); + // printf("From Chan_level aver stream 1 %d =%d\n", aarx, avg_1[aarx]); + } +//avg_0[0] = max(avg_0[0],avg_0[1]); +//avg_1[0] = max(avg_1[0],avg_1[1]); +//avg_0[0]= max(avg_0[0], avg_1[0]); + + avg_0[0] = avg_0[0] + avg_0[1]; + // printf("From Chan_level aver stream 0 final =%d\n", avg_0[0]); + avg_1[0] = avg_1[0] + avg_1[1]; + // printf("From Chan_level aver stream 1 final =%d\n", avg_1[0]); + avg_0[0] = min (avg_0[0], avg_1[0]); + avg_1[0] = avg_0[0]; + + _mm_empty(); + _m_empty(); +#elif defined(__arm__) #endif } -//compute average channel_level of effective (precoded) channel -void dlsch_channel_level_TM3(int **dl_ch_estimates_ext, - LTE_DL_FRAME_PARMS *frame_parms, - int *avg, - uint8_t symbol, - unsigned short nb_rb) -{ + + +/*void dlsch_channel_level_TM34(int **dl_ch_estimates_ext, + LTE_DL_FRAME_PARMS *frame_parms, + int *avg, + uint8_t symbol, + unsigned short nb_rb, + MIMO_mode_t mimo_mode){ + #if defined(__x86_64__)||defined(__i386__) + short rb; unsigned char aarx,nre=12,symbol_mod; __m128i *dl_ch0_128,*dl_ch1_128, dl_ch0_128_tmp, dl_ch1_128_tmp,avg128D; @@ -2986,26 +3675,45 @@ void dlsch_channel_level_TM3(int **dl_ch_estimates_ext, dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[0]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[0]); - prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + if (mimo_mode==LARGE_CDD) + prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) + prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) + prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + // mmtmpD0 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[1]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[1]); - prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + if (mimo_mode==LARGE_CDD) + prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) + prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) + prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + // mmtmpD1 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { dl_ch0_128+=2; dl_ch1_128+=2; - } else { + } + else { dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[2]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[2]); - prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); - // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); + if (mimo_mode==LARGE_CDD) + prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) + prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) + prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); + + // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); dl_ch0_128+=3; @@ -3028,7 +3736,7 @@ void dlsch_channel_level_TM3(int **dl_ch_estimates_ext, #elif defined(__arm__) #endif -} +}*/ //compute average channel_level of effective (precoded) channel void dlsch_channel_level_TM56(int **dl_ch_estimates_ext, @@ -3083,12 +3791,13 @@ void dlsch_channel_level_TM56(int **dl_ch_estimates_ext, if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { dl_ch0_128+=2; dl_ch1_128+=2; - } else { + } + else { dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[2]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[2]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); - // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); + // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); dl_ch0_128+=3; @@ -3184,7 +3893,7 @@ void dlsch_channel_level_TM7(int **dl_bf_ch_estimates_ext, #endif } - +//#define ONE_OVER_2_Q15 16384 void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, int **dl_ch_mag, @@ -3196,14 +3905,15 @@ void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, #if defined(__x86_64__)||defined(__i386__) short *rxF0,*rxF1; - __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b, amp, *rxF0_128; + __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b, *rxF0_128; unsigned char rb,re; int jj = (symbol*frame_parms->N_RB_DL*12); uint8_t symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; uint8_t pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0; rxF0_128 = (__m128i*) &rxdataF_comp[0][jj]; - amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); + //amp = _mm_set1_epi16(ONE_OVER_2_Q15); + // printf("Doing alamouti!\n"); rxF0 = (short*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y @@ -3212,7 +3922,7 @@ void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, ch_mag1 = (__m128i *)&dl_ch_mag[2][jj]; ch_mag0b = (__m128i *)&dl_ch_magb[0][jj]; ch_mag1b = (__m128i *)&dl_ch_magb[2][jj]; - + for (rb=0; rb<nb_rb; rb++) { for (re=0; re<((pilots==0)?12:8); re+=2) { @@ -3221,7 +3931,7 @@ void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, // printf("Alamouti: symbol %d, rb %d, re %d: rxF0 (%d,%d,%d,%d), rxF1 (%d,%d,%d,%d)\n",symbol,rb,re,rxF0[0],rxF0[1],rxF0[2],rxF0[3],rxF1[0],rxF1[1],rxF1[2],rxF1[3]); rxF0[0] = rxF0[0] + rxF1[2]; - rxF0[1] = rxF0[1] - rxF1[3]; + rxF0[1] = rxF0[1] - rxF1[3]; rxF0[2] = rxF0[2] - rxF1[0]; rxF0[3] = rxF0[3] + rxF1[1]; @@ -3240,25 +3950,33 @@ void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, ch_mag0b[1] = _mm_adds_epi16(ch_mag0b[1],ch_mag1b[1]); // account for 1/sqrt(2) scaling at transmission - ch_mag0[0] = _mm_srai_epi16(ch_mag0[0],1); - ch_mag0[1] = _mm_srai_epi16(ch_mag0[1],1); - ch_mag0b[0] = _mm_srai_epi16(ch_mag0b[0],1); - ch_mag0b[1] = _mm_srai_epi16(ch_mag0b[1],1); + //ch_mag0[0] = _mm_srai_epi16(ch_mag0[0],1); + //ch_mag0[1] = _mm_srai_epi16(ch_mag0[1],1); + //ch_mag0b[0] = _mm_srai_epi16(ch_mag0b[0],1); + //ch_mag0b[1] = _mm_srai_epi16(ch_mag0b[1],1); + + //rxF0_128[0] = _mm_mulhi_epi16(rxF0_128[0],amp); + //rxF0_128[0] = _mm_slli_epi16(rxF0_128[0],1); + //rxF0_128[1] = _mm_mulhi_epi16(rxF0_128[1],amp); + //rxF0_128[1] = _mm_slli_epi16(rxF0_128[1],1); + + //rxF0_128[0] = _mm_srai_epi16(rxF0_128[0],1); + //rxF0_128[1] = _mm_srai_epi16(rxF0_128[1],1); + - rxF0_128[0] = _mm_mulhi_epi16(rxF0_128[0],amp); - rxF0_128[0] = _mm_slli_epi16(rxF0_128[0],1); - rxF0_128[1] = _mm_mulhi_epi16(rxF0_128[1],amp); - rxF0_128[1] = _mm_slli_epi16(rxF0_128[1],1); if (pilots==0) { ch_mag0[2] = _mm_adds_epi16(ch_mag0[2],ch_mag1[2]); ch_mag0b[2] = _mm_adds_epi16(ch_mag0b[2],ch_mag1b[2]); - ch_mag0[2] = _mm_srai_epi16(ch_mag0[2],1); - ch_mag0b[2] = _mm_srai_epi16(ch_mag0b[2],1); + //ch_mag0[2] = _mm_srai_epi16(ch_mag0[2],1); + //ch_mag0b[2] = _mm_srai_epi16(ch_mag0b[2],1); + + //rxF0_128[2] = _mm_mulhi_epi16(rxF0_128[2],amp); + //rxF0_128[2] = _mm_slli_epi16(rxF0_128[2],1); + + //rxF0_128[2] = _mm_srai_epi16(rxF0_128[2],1); - rxF0_128[2] = _mm_mulhi_epi16(rxF0_128[2],amp); - rxF0_128[2] = _mm_slli_epi16(rxF0_128[2],1); ch_mag0+=3; ch_mag1+=3; @@ -3297,8 +4015,8 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, unsigned char symbol, unsigned char subframe, uint32_t high_speed_flag, - LTE_DL_FRAME_PARMS *frame_parms) -{ + LTE_DL_FRAME_PARMS *frame_parms) { + unsigned short rb,nb_rb=0; @@ -3339,7 +4057,8 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, 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 (rb=0;rb<frame_parms->N_RB_DL;rb++) { if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; @@ -3352,7 +4071,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, else rb_alloc_ind = 0; - if (rb_alloc_ind == 1) + if (rb_alloc_ind == 1) nb_rb++; // For second half of RBs skip DC carrier @@ -3391,17 +4110,17 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); /* - printf("rb %d\n",rb); - for (i=0;i<12;i++) - printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); - printf("\n"); + printf("rb %d\n",rb); + for (i=0;i<12;i++) + printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); + printf("\n"); */ if (pilots==0) { for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; /* - printf("%d : (%d,%d)\n",(rxF+i-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))]), - ((short*)&rxF[i])[0],((short*)&rxF[i])[1]);*/ + printf("%d : (%d,%d)\n",(rxF+i-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))]), + ((short*)&rxF[i])[0],((short*)&rxF[i])[1]);*/ } dl_ch0_ext+=12; @@ -3433,7 +4152,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, else { // Odd number of RBs for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { #ifdef DEBUG_DLSCH_DEMOD - printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); + printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); #endif skip_half=0; @@ -3448,8 +4167,9 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, else rb_alloc_ind = 0; - if (rb_alloc_ind == 1) - nb_rb++; + if (rb_alloc_ind == 1) + nb_rb++; + // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { @@ -3470,7 +4190,6 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, (l==sss_symb) ) { rb_alloc_ind = 0; } - //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && @@ -3483,10 +4202,11 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD - if (((subframe==0)||(subframe==5)) && - (rb>((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==pss_symb) ) { + + if (((subframe==0)||(subframe==5)) && + (rb>((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==pss_symb) ) { rb_alloc_ind = 0; } @@ -3497,11 +4217,10 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, } if ((frame_parms->frame_type == TDD) && - (subframe==6)) { //TDD Subframe 6 + (subframe==6)){ //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } - if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) @@ -3510,20 +4229,21 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, if (rb_alloc_ind==1) { + #ifdef DEBUG_DLSCH_DEMOD - printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); + printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif if (pilots==0) { - // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); + // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0; i<6; i++) { - rxF_ext[i]=rxF[i]; + rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { @@ -3532,9 +4252,9 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, for (i=0; i<6; i++) { rxF_ext[i]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } dl_ch0_ext+=6; rxF_ext+=6; } else { @@ -3545,12 +4265,12 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } dl_ch0_ext+=12; rxF_ext+=12; } } else { - // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); + // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { @@ -3563,14 +4283,14 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, dl_ch0_ext[j++]=dl_ch0[i]; } } - rxF_ext+=5; + rxF_ext+=5; dl_ch0_ext+=5; } else if (skip_half==2) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",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])); #endif dl_ch0_ext[j++]=dl_ch0[i+6]; } @@ -3584,7 +4304,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",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])); #endif dl_ch0_ext[j++]=dl_ch0[i]; @@ -3596,7 +4316,6 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, } } } - dl_ch0+=12; rxF+=12; } // first half loop @@ -3616,12 +4335,13 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, if (rb_alloc_ind == 1) - nb_rb++; + nb_rb++; // PBCH - if ((subframe==0) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) { + + if ((subframe==0) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } @@ -3640,16 +4360,16 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, //PSS if ((frame_parms->frame_type == TDD) && (subframe==6) && - (l==pss_symb) ) { - rb_alloc_ind = 0; + (l==pss_symb) ) { + rb_alloc_ind = 0; } - + // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); // printf("DC rb %d (%p)\n",rb,rxF); if (rb_alloc_ind==1) { #ifdef DEBUG_DLSCH_DEMOD - printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); + printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif if (pilots==0) { for (i=0; i<6; i++) { @@ -3687,14 +4407,13 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, rxF_ext[j++]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); -#endif +#endif } } dl_ch0_ext+=10; rxF_ext+=10; } // symbol_mod==0 - } // rballoc==1 else { rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; @@ -3704,9 +4423,9 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, rxF+=7; rb++; - for (; rb<frame_parms->N_RB_DL; rb++) { - // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); - // printf("rb %d (%p)\n",rb,rxF); + for (;rb<frame_parms->N_RB_DL;rb++) { + // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); + // printf("rb %d (%p)\n",rb,rxF); skip_half=0; if (rb < 32) @@ -3720,14 +4439,13 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, else rb_alloc_ind = 0; - if (rb_alloc_ind == 1) - nb_rb++; + if (rb_alloc_ind == 1) + nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } - //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; @@ -3738,13 +4456,11 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } - //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; - if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { @@ -3752,6 +4468,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, } //PSS + if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) @@ -3759,6 +4476,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, } if ((frame_parms->frame_type == TDD) && + (subframe==6)) { //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; @@ -3771,26 +4489,26 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, } if (rb_alloc_ind==1) { -#ifdef DEBUG_DLSCH_DEMOD - printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); +#ifdef DEBUG_DLSCH_DEMOD + printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif /* - printf("rb %d\n",rb); + printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0) { - // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); + // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; -#ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); +#ifdef DEBUG_DLSCH_DEMOD + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } dl_ch0_ext+=6; rxF_ext+=6; @@ -3800,9 +4518,9 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, for (i=0; i<6; i++) { rxF_ext[i]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } dl_ch0_ext+=6; rxF_ext+=6; @@ -3812,14 +4530,14 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } dl_ch0_ext+=12; rxF_ext+=12; } } else { - // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); + // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { @@ -3827,7 +4545,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",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])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } @@ -3840,7 +4558,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",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])); #endif dl_ch0_ext[j++]=dl_ch0[i+6]; } @@ -3854,12 +4572,11 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",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])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } - dl_ch0_ext+=10; rxF_ext+=10; } @@ -3871,7 +4588,7 @@ unsigned short dlsch_extract_rbs_single(int **rxdataF, } } } - + return(nb_rb/frame_parms->nb_antennas_rx); } @@ -3886,9 +4603,8 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF, unsigned char symbol, unsigned char subframe, uint32_t high_speed_flag, - LTE_DL_FRAME_PARMS *frame_parms) -{ - + LTE_DL_FRAME_PARMS *frame_parms, + MIMO_mode_t mimo_mode) { int prb,nb_rb=0; int prb_off,prb_off2; @@ -3926,7 +4642,7 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF, } pmi_loc = pmi_ext; - + // pointers to extracted RX signals and channel estimates rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; @@ -3934,95 +4650,102 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF, for (prb=0; prb<frame_parms->N_RB_DL; prb++) { skip_half=0; - + if (prb < 32) - rb_alloc_ind = (rb_alloc[0]>>prb) & 1; + rb_alloc_ind = (rb_alloc[0]>>prb) & 1; else if (prb < 64) - rb_alloc_ind = (rb_alloc[1]>>(prb-32)) & 1; + rb_alloc_ind = (rb_alloc[1]>>(prb-32)) & 1; else if (prb < 96) - rb_alloc_ind = (rb_alloc[2]>>(prb-64)) & 1; + rb_alloc_ind = (rb_alloc[2]>>(prb-64)) & 1; else if (prb < 100) - rb_alloc_ind = (rb_alloc[3]>>(prb-96)) & 1; + rb_alloc_ind = (rb_alloc[3]>>(prb-96)) & 1; else - rb_alloc_ind = 0; + rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; - + if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs - // PBCH - if ((subframe==0) && - (prb>=((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) { - rb_alloc_ind = 0; - // printf("symbol %d / rb %d: skipping PBCH REs\n",symbol,prb); - } - - //SSS - - if (((subframe==0)||(subframe==5)) && - (prb>=((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l==sss_symb) ) { - rb_alloc_ind = 0; - // printf("symbol %d / rb %d: skipping SSS REs\n",symbol,prb); - } - - - - //PSS in subframe 0/5 if FDD - if (frame_parms->frame_type == FDD) { //FDD - if (((subframe==0)||(subframe==5)) && - (prb>=((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l==pss_symb) ) { - rb_alloc_ind = 0; - // printf("symbol %d / rb %d: skipping PSS REs\n",symbol,prb); - } - } - - if ((frame_parms->frame_type == TDD) && - (subframe==6)) { //TDD Subframe 6 - if ((prb>=((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l==pss_symb) ) { - rb_alloc_ind = 0; - } - } - - if (rb_alloc_ind==1) { // PRB is allocated - - - - prb_off = 12*prb; - prb_off2 = 1+(12*(prb-(frame_parms->N_RB_DL>>1))); - dl_ch0p = dl_ch0+(12*prb); - dl_ch1p = dl_ch1+(12*prb); - if (prb<(frame_parms->N_RB_DL>>1)){ - rxF = &rxdataF[aarx][prb_off+ - frame_parms->first_carrier_offset + - (symbol*(frame_parms->ofdm_symbol_size))]; - } - else { - rxF = &rxdataF[aarx][prb_off2+ - (symbol*(frame_parms->ofdm_symbol_size))]; - } + // PBCH + if ((subframe==0) && + (prb>=((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) { + rb_alloc_ind = 0; + // printf("symbol %d / rb %d: skipping PBCH REs\n",symbol,prb); + } + + //SSS + + if (((subframe==0)||(subframe==5)) && + (prb>=((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l==sss_symb) ) { + rb_alloc_ind = 0; + // printf("symbol %d / rb %d: skipping SSS REs\n",symbol,prb); + } + + + + //PSS in subframe 0/5 if FDD + if (frame_parms->frame_type == FDD) { //FDD + if (((subframe==0)||(subframe==5)) && + (prb>=((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l==pss_symb) ) { + rb_alloc_ind = 0; + // printf("symbol %d / rb %d: skipping PSS REs\n",symbol,prb); + } + } + + if ((frame_parms->frame_type == TDD) && + (subframe==6)) { //TDD Subframe 6 + if ((prb>=((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l==pss_symb) ) { + rb_alloc_ind = 0; + } + } + + if (rb_alloc_ind==1) { // PRB is allocated + + + + prb_off = 12*prb; + prb_off2 = 1+(12*(prb-(frame_parms->N_RB_DL>>1))); + dl_ch0p = dl_ch0+(12*prb); + dl_ch1p = dl_ch1+(12*prb); + if (prb<(frame_parms->N_RB_DL>>1)){ + rxF = &rxdataF[aarx][prb_off+ + frame_parms->first_carrier_offset + + (symbol*(frame_parms->ofdm_symbol_size))]; + } + else { + rxF = &rxdataF[aarx][prb_off2+ + (symbol*(frame_parms->ofdm_symbol_size))]; + } + + /* + if (mimo_mode <= PUSCH_PRECODING1) *pmi_loc = (pmi>>((prb>>2)<<1))&3; + else + *pmi_loc=(pmi>>prb)&1;*/ + + *pmi_loc = get_pmi(frame_parms->N_RB_DL,mimo_mode,pmi,prb); pmi_loc++; - - + + if (pilots == 0) { - + memcpy(dl_ch0_ext,dl_ch0p,12*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1p,12*sizeof(int)); memcpy(rxF_ext,rxF,12*sizeof(int)); - dl_ch0_ext +=12; - dl_ch1_ext +=12; - rxF_ext +=12; + dl_ch0_ext +=12; + dl_ch1_ext +=12; + rxF_ext +=12; } else { // pilots==1 j=0; for (i=0; i<12; i++) { @@ -4036,280 +4759,283 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF, dl_ch1_ext[j++]=dl_ch1p[i]; } } - dl_ch0_ext+=8; - dl_ch1_ext+=8; - rxF_ext+=8; + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; } // pilots==1 - } + } } else { // Odd number of RBs // PBCH - if ((subframe==0) && - (prb>((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) { - rb_alloc_ind = 0; - // printf("symbol %d / rb %d: skipping PBCH REs\n",symbol,prb); - } - - //SSS - - if (((subframe==0)||(subframe==5)) && - (prb>((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l==sss_symb) ) { - rb_alloc_ind = 0; - // printf("symbol %d / rb %d: skipping SSS REs\n",symbol,prb); - } - - - - //PSS in subframe 0/5 if FDD - if (frame_parms->frame_type == FDD) { //FDD - if (((subframe==0)||(subframe==5)) && - (prb>((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l==pss_symb) ) { - rb_alloc_ind = 0; - // printf("symbol %d / rb %d: skipping PSS REs\n",symbol,prb); - } - } - - if ((frame_parms->frame_type == TDD) && - ((subframe==1) || (subframe==6))) { //TDD Subframe 1-6 - if ((prb>((frame_parms->N_RB_DL>>1)-3)) && - (prb<((frame_parms->N_RB_DL>>1)+3)) && - (l==pss_symb) ) { - rb_alloc_ind = 0; - } - } - - if (rb_alloc_ind == 1) { - skip_half=0; - - //Check if we have to drop half a PRB due to PSS/SSS/PBCH - // skip_half == 0 means full PRB - // skip_half == 1 means first half is used (leftmost half-PRB from PSS/SSS/PBCH) - // skip_half == 2 means second half is used (rightmost half-PRB from PSS/SSS/PBCH) - //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 - if ((subframe==0) && - (prb==((frame_parms->N_RB_DL>>1)-3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) - skip_half=1; - else if ((subframe==0) && - (prb==((frame_parms->N_RB_DL>>1)+3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) - skip_half=2; - - //SSS - if (((subframe==0)||(subframe==5)) && - (prb==((frame_parms->N_RB_DL>>1)-3)) && - (l==sss_symb)) - skip_half=1; - else if (((subframe==0)||(subframe==5)) && - (prb==((frame_parms->N_RB_DL>>1)+3)) && - (l==sss_symb)) - skip_half=2; - - //PSS Subframe 0,5 - if (((frame_parms->frame_type == FDD) && - (((subframe==0)||(subframe==5)))) || //FDD Subframes 0,5 - ((frame_parms->frame_type == TDD) && - (((subframe==1) || (subframe==6))))) { //TDD Subframes 1,6 - - if ((prb==((frame_parms->N_RB_DL>>1)-3)) && - (l==pss_symb)) - skip_half=1; - else if ((prb==((frame_parms->N_RB_DL>>1)+3)) && - (l==pss_symb)) - skip_half=2; - } - - - prb_off = 12*prb; - prb_off2 = 7+(12*(prb-(frame_parms->N_RB_DL>>1)-1)); - dl_ch0p = dl_ch0+(12*prb); - dl_ch1p = dl_ch1+(12*prb); - - if (prb<=(frame_parms->N_RB_DL>>1)){ - rxF = &rxdataF[aarx][prb_off+ - frame_parms->first_carrier_offset + - (symbol*(frame_parms->ofdm_symbol_size))]; - } - else { - rxF = &rxdataF[aarx][prb_off2+ - (symbol*(frame_parms->ofdm_symbol_size))]; - } + if ((subframe==0) && + (prb>((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) { + rb_alloc_ind = 0; + // printf("symbol %d / rb %d: skipping PBCH REs\n",symbol,prb); + } + + //SSS + + if (((subframe==0)||(subframe==5)) && + (prb>((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l==sss_symb) ) { + rb_alloc_ind = 0; + // printf("symbol %d / rb %d: skipping SSS REs\n",symbol,prb); + } + + + + //PSS in subframe 0/5 if FDD + if (frame_parms->frame_type == FDD) { //FDD + if (((subframe==0)||(subframe==5)) && + (prb>((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l==pss_symb) ) { + rb_alloc_ind = 0; + // printf("symbol %d / rb %d: skipping PSS REs\n",symbol,prb); + } + } + + if ((frame_parms->frame_type == TDD) && + ((subframe==1) || (subframe==6))) { //TDD Subframe 1-6 + if ((prb>((frame_parms->N_RB_DL>>1)-3)) && + (prb<((frame_parms->N_RB_DL>>1)+3)) && + (l==pss_symb) ) { + rb_alloc_ind = 0; + } + } + + if (rb_alloc_ind == 1) { + skip_half=0; + + //Check if we have to drop half a PRB due to PSS/SSS/PBCH + // skip_half == 0 means full PRB + // skip_half == 1 means first half is used (leftmost half-PRB from PSS/SSS/PBCH) + // skip_half == 2 means second half is used (rightmost half-PRB from PSS/SSS/PBCH) + //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 + if ((subframe==0) && + (prb==((frame_parms->N_RB_DL>>1)-3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) + skip_half=1; + else if ((subframe==0) && + (prb==((frame_parms->N_RB_DL>>1)+3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) + skip_half=2; + + //SSS + if (((subframe==0)||(subframe==5)) && + (prb==((frame_parms->N_RB_DL>>1)-3)) && + (l==sss_symb)) + skip_half=1; + else if (((subframe==0)||(subframe==5)) && + (prb==((frame_parms->N_RB_DL>>1)+3)) && + (l==sss_symb)) + skip_half=2; + + //PSS Subframe 0,5 + if (((frame_parms->frame_type == FDD) && + (((subframe==0)||(subframe==5)))) || //FDD Subframes 0,5 + ((frame_parms->frame_type == TDD) && + (((subframe==1) || (subframe==6))))) { //TDD Subframes 1,6 + + if ((prb==((frame_parms->N_RB_DL>>1)-3)) && + (l==pss_symb)) + skip_half=1; + else if ((prb==((frame_parms->N_RB_DL>>1)+3)) && + (l==pss_symb)) + skip_half=2; + } + + + prb_off = 12*prb; + prb_off2 = 7+(12*(prb-(frame_parms->N_RB_DL>>1)-1)); + dl_ch0p = dl_ch0+(12*prb); + dl_ch1p = dl_ch1+(12*prb); + + if (prb<=(frame_parms->N_RB_DL>>1)){ + rxF = &rxdataF[aarx][prb_off+ + frame_parms->first_carrier_offset + + (symbol*(frame_parms->ofdm_symbol_size))]; + } + else { + rxF = &rxdataF[aarx][prb_off2+ + (symbol*(frame_parms->ofdm_symbol_size))]; + } #ifdef DEBUG_DLSCH_DEMOD - printf("symbol %d / rb %d: alloc %d skip_half %d (rxF %p, rxF_ext %p) prb_off (%d,%d)\n",symbol,prb,rb_alloc_ind,skip_half,rxF,rxF_ext,prb_off,prb_off2); + printf("symbol %d / rb %d: alloc %d skip_half %d (rxF %p, rxF_ext %p) prb_off (%d,%d)\n",symbol,prb,rb_alloc_ind,skip_half,rxF,rxF_ext,prb_off,prb_off2); #endif - *pmi_loc = (pmi>>((prb>>2)<<1))&3; - // printf("symbol_mod %d (pilots %d) rb %d, sb %d, pmi %d (pmi_loc %p,rxF %p, ch00 %p, ch01 %p, rxF_ext %p dl_ch0_ext %p dl_ch1_ext %p)\n",symbol_mod,pilots,rb,rb>>2,*pmi_loc,pmi_loc,rxF,dl_ch0, dl_ch1, rxF_ext,dl_ch0_ext,dl_ch1_ext); - + /* if (mimo_mode <= PUSCH_PRECODING1) + *pmi_loc = (pmi>>((prb>>2)<<1))&3; + else + *pmi_loc=(pmi>>prb)&1; + // printf("symbol_mod %d (pilots %d) rb %d, sb %d, pmi %d (pmi_loc %p,rxF %p, ch00 %p, ch01 %p, rxF_ext %p dl_ch0_ext %p dl_ch1_ext %p)\n",symbol_mod,pilots,prb,prb>>2,*pmi_loc,pmi_loc,rxF,dl_ch0, dl_ch1, rxF_ext,dl_ch0_ext,dl_ch1_ext); +*/ + *pmi_loc = get_pmi(frame_parms->N_RB_DL,mimo_mode,pmi,prb); pmi_loc++; - if (prb != (frame_parms->N_RB_DL>>1)) { // This PRB is not around DC - if (pilots==0) { - if (skip_half==1) { - memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); - memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); - memcpy(rxF_ext,rxF,6*sizeof(int32_t)); + if (prb != (frame_parms->N_RB_DL>>1)) { // This PRB is not around DC + if (pilots==0) { + if (skip_half==1) { + memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); + memcpy(rxF_ext,rxF,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD - for (i=0;i<6;i++) - printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + for (i=0;i<6;i++) + printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - dl_ch0_ext+=6; - dl_ch1_ext+=6; - rxF_ext+=6; - } else if (skip_half==2) { - memcpy(dl_ch0_ext,dl_ch0p+6,6*sizeof(int32_t)); - memcpy(dl_ch1_ext,dl_ch1p+6,6*sizeof(int32_t)); - memcpy(rxF_ext,rxF+6,6*sizeof(int32_t)); + dl_ch0_ext+=6; + dl_ch1_ext+=6; + rxF_ext+=6; + } else if (skip_half==2) { + memcpy(dl_ch0_ext,dl_ch0p+6,6*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1p+6,6*sizeof(int32_t)); + memcpy(rxF_ext,rxF+6,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD - for (i=0;i<6;i++) - printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + for (i=0;i<6;i++) + printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - dl_ch0_ext+=6; - dl_ch1_ext+=6; - rxF_ext+=6; - } else { // skip_half==0 - memcpy(dl_ch0_ext,dl_ch0p,12*sizeof(int32_t)); - memcpy(dl_ch1_ext,dl_ch1p,12*sizeof(int32_t)); - memcpy(rxF_ext,rxF,12*sizeof(int32_t)); + dl_ch0_ext+=6; + dl_ch1_ext+=6; + rxF_ext+=6; + } else { // skip_half==0 + memcpy(dl_ch0_ext,dl_ch0p,12*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1p,12*sizeof(int32_t)); + memcpy(rxF_ext,rxF,12*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD - for (i=0;i<12;i++) - printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + for (i=0;i<12;i++) + printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - dl_ch0_ext+=12; - dl_ch1_ext+=12; - rxF_ext+=12; - } - } else { // pilots=1 - j=0; - - if (skip_half==1) { - for (i=0; i<6; i++) { - if ((i!=frame_parms->nushift) && - (i!=((frame_parms->nushift+3)%6))) { - rxF_ext[j]=rxF[i]; + dl_ch0_ext+=12; + dl_ch1_ext+=12; + rxF_ext+=12; + } + } else { // pilots=1 + j=0; + + if (skip_half==1) { + for (i=0; i<6; i++) { + if ((i!=frame_parms->nushift) && + (i!=((frame_parms->nushift+3)%6))) { + rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("(pilots,skip1)extract rb %d, re %d (%d)=> (%d,%d)\n",prb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + printf("(pilots,skip1)extract rb %d, re %d (%d)=> (%d,%d)\n",prb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif - dl_ch0_ext[j]=dl_ch0p[i]; - dl_ch1_ext[j++]=dl_ch1p[i]; - } - } - dl_ch0_ext+=4; - dl_ch1_ext+=4; - rxF_ext+=4; - } else if (skip_half==2) { - for (i=0; i<6; i++) { - if ((i!=frame_parms->nushift) && - (i!=((frame_parms->nushift+3)%6))) { - rxF_ext[j]=rxF[(i+6)]; + dl_ch0_ext[j]=dl_ch0p[i]; + dl_ch1_ext[j++]=dl_ch1p[i]; + } + } + dl_ch0_ext+=4; + dl_ch1_ext+=4; + rxF_ext+=4; + } else if (skip_half==2) { + for (i=0; i<6; i++) { + if ((i!=frame_parms->nushift) && + (i!=((frame_parms->nushift+3)%6))) { + rxF_ext[j]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("(pilots,skip2)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + printf("(pilots,skip2)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif - dl_ch0_ext[j]=dl_ch0p[i+6]; - dl_ch1_ext[j++]=dl_ch1p[i+6]; - } - } - dl_ch0_ext+=4; - dl_ch1_ext+=4; - rxF_ext+=4; - - } else { //skip_half==0 - for (i=0; i<12; i++) { - if ((i!=frame_parms->nushift) && - (i!=frame_parms->nushift+3) && - (i!=frame_parms->nushift+6) && - (i!=((frame_parms->nushift+9)%12))) { - rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0p[i+6]; + dl_ch1_ext[j++]=dl_ch1p[i+6]; + } + } + dl_ch0_ext+=4; + dl_ch1_ext+=4; + rxF_ext+=4; + + } else { //skip_half==0 + for (i=0; i<12; i++) { + if ((i!=frame_parms->nushift) && + (i!=frame_parms->nushift+3) && + (i!=frame_parms->nushift+6) && + (i!=((frame_parms->nushift+9)%12))) { + rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("(pilots)extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); + printf("(pilots)extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif - dl_ch0_ext[j] =dl_ch0p[i]; - dl_ch1_ext[j++]=dl_ch1p[i]; - } - } - dl_ch0_ext+=8; - dl_ch1_ext+=8; - rxF_ext+=8; - } //skip_half==0 - } //pilots==1 - } else { // Do middle RB (around DC) - - if (pilots==0) { - memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); - memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); - memcpy(rxF_ext,rxF,6*sizeof(int32_t)); + dl_ch0_ext[j] =dl_ch0p[i]; + dl_ch1_ext[j++]=dl_ch1p[i]; + } + } + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; + } //skip_half==0 + } //pilots==1 + } else { // Do middle RB (around DC) + + if (pilots==0) { + memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); + memcpy(rxF_ext,rxF,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD - for (i=0; i<6; i++) { - printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); - } + for (i=0; i<6; i++) { + printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + } #endif - rxF_ext+=6; - dl_ch0_ext+=6; - dl_ch1_ext+=6; - dl_ch0p+=6; - dl_ch1p+=6; - - rxF = &rxdataF[aarx][1+((symbol*(frame_parms->ofdm_symbol_size)))]; - - memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); - memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); - memcpy(rxF_ext,rxF,6*sizeof(int32_t)); + rxF_ext+=6; + dl_ch0_ext+=6; + dl_ch1_ext+=6; + dl_ch0p+=6; + dl_ch1p+=6; + + rxF = &rxdataF[aarx][1+((symbol*(frame_parms->ofdm_symbol_size)))]; + + memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); + memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); + memcpy(rxF_ext,rxF,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD - for (i=0; i<6; i++) { - printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); - } + for (i=0; i<6; i++) { + printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + } #endif - rxF_ext+=6; - dl_ch0_ext+=6; - dl_ch1_ext+=6; - } else { // pilots==1 - j=0; - - for (i=0; i<6; i++) { - if ((i!=frame_parms->nushift) && - (i!=((frame_parms->nushift+3)%6))) { - dl_ch0_ext[j]=dl_ch0p[i]; - dl_ch1_ext[j]=dl_ch1p[i]; - rxF_ext[j++]=rxF[i]; + rxF_ext+=6; + dl_ch0_ext+=6; + dl_ch1_ext+=6; + } else { // pilots==1 + j=0; + + for (i=0; i<6; i++) { + if ((i!=frame_parms->nushift) && + (i!=((frame_parms->nushift+3)%6))) { + dl_ch0_ext[j]=dl_ch0p[i]; + dl_ch1_ext[j]=dl_ch1p[i]; + rxF_ext[j++]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("(pilots)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF[i],*(1+(short*)&rxF[i])); + printf("(pilots)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF[i],*(1+(short*)&rxF[i])); #endif - } - } - rxF = &rxdataF[aarx][1+symbol*(frame_parms->ofdm_symbol_size)]; - - for (; i<12; i++) { - if ((i!=((frame_parms->nushift+6)%12)) && - (i!=((frame_parms->nushift+9)%12))) { - dl_ch0_ext[j]=dl_ch0p[i]; - dl_ch1_ext[j]=dl_ch1p[i]; - rxF_ext[j++]=rxF[i-6]; + } + } + rxF = &rxdataF[aarx][1+symbol*(frame_parms->ofdm_symbol_size)]; + + for (; i<12; i++) { + if ((i!=((frame_parms->nushift+6)%12)) && + (i!=((frame_parms->nushift+9)%12))) { + dl_ch0_ext[j]=dl_ch0p[i]; + dl_ch1_ext[j]=dl_ch1p[i]; + rxF_ext[j++]=rxF[i-6]; #ifdef DEBUG_DLSCH_DEMOD - printf("(pilots)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF[1+i-6],*(1+(short*)&rxF[1+i-6])); + printf("(pilots)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF[1+i-6],*(1+(short*)&rxF[1+i-6])); #endif - } - } - - dl_ch0_ext+=8; - dl_ch1_ext+=8; - rxF_ext+=8; - } //pilots==1 - } // if Middle PRB - } // if odd PRB + } + } + + dl_ch0_ext+=8; + dl_ch1_ext+=8; + rxF_ext+=8; + } //pilots==1 + } // if Middle PRB + } // if odd PRB } // if rballoc==1 - } // for prb + } // for prb } // for aarx - return(nb_rb/frame_parms->nb_antennas_rx); } @@ -4385,7 +5111,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, else rb_alloc_ind = 0; - if (rb_alloc_ind == 1) + if (rb_alloc_ind == 1) nb_rb++; // For second half of RBs skip DC carrier @@ -4393,7 +5119,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; //dl_ch0++; } - + // PBCH if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; @@ -4454,23 +5180,23 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, j=0; - for (i=0; i<12; i++){ + for (i=0; i<12; i++){ if (frame_parms->Ncp==0){ - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j++]=dl_ch0[i]; + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ + rxF_ext[j] = rxF[i]; + dl_ch0_ext[j++]=dl_ch0[i]; } } else{ - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ - rxF_ext[j] = rxF[i]; + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + rxF_ext[j] = rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; - } + } } - - } - + + } + dl_ch0_ext+=9-frame_parms->Ncp; - rxF_ext+=9-frame_parms->Ncp; + rxF_ext+=9-frame_parms->Ncp; } else { msg("dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n"); @@ -4569,7 +5295,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -4581,7 +5307,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, for (i=0; i<6; i++) { rxF_ext[i]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -4609,7 +5335,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4622,7 +5348,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4656,7 +5382,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4665,11 +5391,11 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } else{ for (i=0; i<6; i++) { - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4684,7 +5410,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4693,11 +5419,11 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } else { for (i=0; i<6; i++) { - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4707,35 +5433,35 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } else { - for (i=0; i<12; i++){ + for (i=0; i<12; i++){ if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j++] = dl_ch0[i]; + rxF_ext[j] = rxF[i]; + dl_ch0_ext[j++] = dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d, j %d => (%d,%d)\n",symbol,rb,i,j-1,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i])); #endif } } else{ - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j++]=dl_ch0[i]; + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + rxF_ext[j] = rxF[i]; + dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif - } + } } - - } - + + } + dl_ch0_ext+=9-frame_parms->Ncp; - rxF_ext+=9-frame_parms->Ncp; - } - + rxF_ext+=9-frame_parms->Ncp; + } + } else { msg("dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n"); exit(-1); - + } } @@ -4792,7 +5518,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -4802,7 +5528,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -4816,7 +5542,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4828,7 +5554,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -4838,52 +5564,52 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } else if(pilots==0 && uespec_pilots==1) { j=0; - for (i=0; i<6; i++) { + for (i=0; i<6; i++) { if (frame_parms->Ncp==0){ - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ - dl_ch0_ext[j]=dl_ch0[i]; - rxF_ext[j++] = rxF[i]; + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ + dl_ch0_ext[j]=dl_ch0[i]; + rxF_ext[j++] = rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } else { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ - dl_ch0_ext[j]=dl_ch0[i]; - rxF_ext[j++] = rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + rxF_ext[j++] = rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } - } - + } + rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { if (frame_parms->Ncp==0){ - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } else { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ - dl_ch0_ext[j]=dl_ch0[i]; - rxF_ext[j++] = rxF[(1+i-6)]; + dl_ch0_ext[j]=dl_ch0[i]; + rxF_ext[j++] = rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } } - + dl_ch0_ext+=9-frame_parms->Ncp; - rxF_ext+=9-frame_parms->Ncp; - - }// symbol_mod==0 + rxF_ext+=9-frame_parms->Ncp; + + }// symbol_mod==0 } // rballoc==1 else { @@ -4976,7 +5702,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -4989,7 +5715,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, for (i=0; i<6; i++) { rxF_ext[i]=rxF[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -5003,7 +5729,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } @@ -5020,7 +5746,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -5033,7 +5759,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -5065,7 +5791,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -5074,11 +5800,11 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } else{ for (i=0; i<6; i++) { - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -5093,7 +5819,7 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, rxF_ext[j]=rxF[i+6]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -5102,11 +5828,11 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } else { for (i=0; i<6; i++) { - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } @@ -5115,31 +5841,31 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, } } else { - for (i=0; i<12; i++){ + for (i=0; i<12; i++){ if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j++]=dl_ch0[i]; + rxF_ext[j] = rxF[i]; + dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } else{ - if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j++]=dl_ch0[i]; + if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ + rxF_ext[j] = rxF[i]; + dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD - printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); + printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } - } - + } + dl_ch0_ext+=9-frame_parms->Ncp; - rxF_ext+=9-frame_parms->Ncp; + rxF_ext+=9-frame_parms->Ncp; } - + }// pilots=0 } @@ -5154,16 +5880,14 @@ unsigned short dlsch_extract_rbs_TM7(int **rxdataF, return(nb_rb/frame_parms->nb_antennas_rx); } - - //============================================================================================== #ifdef USER_MODE -void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint16_t coded_bits_per_codeword,int round) -{ +void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid) +{ unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; char fname[32],vname[32]; int N_RB_DL=ue->frame_parms.N_RB_DL; @@ -5222,7 +5946,13 @@ void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint16_t coded_ */ sprintf(fname,"dlsch%d_r%d_rho.m",eNB_id,round); sprintf(vname,"dl_rho_r%d_%d",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_rho_ext[0],12*N_RB_DL*nsymb,1,1); + + write_output(fname,vname,ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_rho_ext[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); + + sprintf(fname,"dlsch%d_r%d_rho2.m",eNB_id,round); + sprintf(vname,"dl_rho2_r%d_%d",eNB_id,round); + + write_output(fname,vname,ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_rho2_ext[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_rxF_r%d_comp0.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_comp0",eNB_id,round); @@ -5230,12 +5960,12 @@ void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint16_t coded_ if (ue->frame_parms.nb_antenna_ports_eNB == 2) { sprintf(fname,"dlsch%d_rxF_r%d_comp1.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_comp1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[0][round],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); } sprintf(fname,"dlsch%d_rxF_r%d_llr.m",eNB_id,round); sprintf(vname,"dl%d_r%d_llr",eNB_id,round); - write_output(fname,vname, ue->pdsch_vars[subframe&0x1][eNB_id]->llr[0],coded_bits_per_codeword,1,0); + write_output(fname,vname, ue->pdsch_vars[subframe&0x1][eNB_id]->llr[0],coded_bits_per_codeword[0],1,0); sprintf(fname,"dlsch%d_r%d_mag1.m",eNB_id,round); sprintf(vname,"dl%d_r%d_mag1",eNB_id,round); write_output(fname,vname,ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb,1,1); @@ -5257,7 +5987,7 @@ void print_bytes(char *s,__m128i *x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3],tempb[4],tempb[5],tempb[6],tempb[7], tempb[8],tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15] - ); + ); } diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c index 8165bc1f23f085e0df9a7b647cca08eaa3afbbf7..e2de78f9caf4b903bb30051095fc83d9774b8b1d 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c @@ -31,11 +31,15 @@ */ #include "PHY/defs.h" +#include "PHY/TOOLS/defs.h" #include "PHY/extern.h" #include "defs.h" #include "extern.h" #include "PHY/sse_intrin.h" +//#define DEBUG_LLR_SIC + + int16_t zero[8] __attribute__ ((aligned(16))) = {0,0,0,0,0,0,0,0}; int16_t ones[8] __attribute__ ((aligned(16))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; #if defined(__x86_64__) || defined(__i386__) @@ -633,7 +637,7 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, uint16_t nb_rb, uint16_t pbch_pss_sss_adjust, int16_t **llr32p, - uint8_t beamforming_mode) + uint8_t beamforming_mode) { uint32_t *rxF = (uint32_t*)&rxdataF_comp[0][((int32_t)symbol*frame_parms->N_RB_DL*12)]; @@ -667,11 +671,11 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, } - // printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); - + //printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); + //printf("ll32p=%p , dlsch_llr=%p, symbol=%d, flag=%d \n", llr32, dlsch_llr, symbol, first_symbol_flag); for (i=0; i<len; i++) { *llr32 = *rxF; - // printf("llr %d : (%d,%d)\n",i,((int16_t*)llr32)[0],((int16_t*)llr32)[1]); + //printf("llr %d : (%d,%d)\n",i,((int16_t*)llr32)[0],((int16_t*)llr32)[1]); rxF++; llr32++; } @@ -681,6 +685,115 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, return(0); } +int32_t dlsch_qpsk_llr_SIC(LTE_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **sic_buffer, //Q15 + int32_t **rho_i, + short *dlsch_llr, + uint8_t num_pdcch_symbols, + uint16_t nb_rb, + uint8_t subframe, + uint32_t rb_alloc, + uint16_t mod_order_0, + LTE_UE_DLSCH_t *dlsch0) +{ + + int16_t rho_amp_x0[2*frame_parms->N_RB_DL*12]; + int16_t rho_rho_amp_x0[2*frame_parms->N_RB_DL*12]; + uint16_t amp_tmp; + uint16_t *llr16=(uint16_t*)dlsch_llr; + int i, len, nsymb; + uint8_t symbol, symbol_mod; + int len_acc=0; + uint16_t *sic_data; + uint16_t pbch_pss_sss_adjust; + + nsymb = (frame_parms->Ncp==0) ? 14:12; + + for (symbol=num_pdcch_symbols; symbol<nsymb; symbol++) { + uint16_t *rxF = (uint16_t*)(&rxdataF_comp[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + int16_t *rho_1=(int16_t*)(&rho_i[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + sic_data = (uint16_t*)&sic_buffer[0][((int16_t)len_acc)]; + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + + + + if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) //pilots=1 + amp_tmp=0x1fff;//dlsch0->sqrt_rho_b; already taken into account + else //pilots=0 + amp_tmp=0x1fff;//1.5*dlsch0->sqrt_rho_a; already taken into account + + if (mod_order_0==6) + amp_tmp=amp_tmp<<1; // to compensate for >> 1 shift in modulation to avoid overflow + + + pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,2,subframe,symbol); + + if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { + if (frame_parms->mode1_flag==0) + len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3); + else + len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6); + } else { + len = (nb_rb*12) - pbch_pss_sss_adjust; + } + + // printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); + + len_acc+=len; //accumulated length; this is done because in sic_buffer we have only data symbols + + multadd_complex_vector_real_scalar((int16_t *)sic_data, + amp_tmp, + (int16_t *)rho_amp_x0, //this is in Q13 + 1, + len); + + mult_cpx_vector((int16_t *)rho_1, //Q15 + (int16_t *)rho_amp_x0, //Q13 + (int16_t*)rho_rho_amp_x0, + len, + 13); + +#ifdef DEBUG_LLR_SIC + write_output("rho_for_multipl.m","rho_for_m", rho_1,len,1, + symbol==num_pdcch_symbols ? 15 : + symbol==nsymb-1 ? 14 : 13); + + write_output("rho_rho_in_llr.m","rho2", rho_rho_amp_x0,len,1, + symbol==num_pdcch_symbols ? 15 : + symbol==nsymb-1 ? 14 : 13); +#endif + + sub_cpx_vector16((int16_t *)rxF, + (int16_t *)rho_rho_amp_x0, + //(int16_t *)clean_x1, + (int16_t *)rxF, + len*2); + +#ifdef DEBUG_LLR_SIC + write_output("rxFdata_comp1_after.m","rxF_a", rxF,len,1,1); + write_output("rxF_comp1.m","rxF_1_comp", rxF,len,1, + symbol==num_pdcch_symbols ? 15 : + symbol==nsymb-1 ? 14 : 13); +#endif + + //this is for QPSK only!!! + for (i=0; i<len*2; i++) { + *llr16 =rxF[i]; + //printf("llr %d : (%d,%d)\n",i,((int16_t*)llr32)[0],((int16_t*)llr32)[1]); + llr16++; + } + + } + + // printf("dlsch_qpsk_llr_SIC: acc_len=%d\n",len_acc); + + return(0); +} + + //---------------------------------------------------------------------------------------------- // 16-QAM //---------------------------------------------------------------------------------------------- @@ -754,10 +867,13 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms, else *llr32p += (len<<2); + // printf("len=%d\n", len); len_mod4 = len&3; + // printf("len_mod4=%d\n", len_mod4); len>>=2; // length in quad words (4 REs) + // printf("len>>=2=%d\n", len); len+=(len_mod4==0 ? 0 : 1); - + // printf("len+=%d\n", len); for (i=0; i<len; i++) { #if defined(__x86_64__) || defined(__i386) @@ -808,6 +924,112 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms, #endif } +void dlsch_16qam_llr_SIC (LTE_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **sic_buffer, //Q15 + int32_t **rho_i, + int16_t *dlsch_llr, + uint8_t num_pdcch_symbols, + int32_t **dl_ch_mag, + uint16_t nb_rb, + uint8_t subframe, + uint32_t rb_alloc, + uint16_t mod_order_0, + LTE_UE_DLSCH_t *dlsch0 + ) +{ + int16_t rho_amp_x0[2*frame_parms->N_RB_DL*12]; + int16_t rho_rho_amp_x0[2*frame_parms->N_RB_DL*12]; + uint16_t amp_tmp; + uint32_t *llr32=(uint32_t*)dlsch_llr; + int i, len, nsymb; + uint8_t symbol, symbol_mod; + int len_acc=0; + uint16_t *sic_data; + uint16_t pbch_pss_sss_adjust; + unsigned char len_mod4=0; + __m128i llr128[2]; + __m128i *ch_mag; + nsymb = (frame_parms->Ncp==0) ? 14:12; + + for (symbol=num_pdcch_symbols; symbol<nsymb; symbol++) { + uint16_t *rxF = (uint16_t*)(&rxdataF_comp[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + int16_t *rho_1=(int16_t*)(&rho_i[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + ch_mag = (__m128i*)(&dl_ch_mag[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + sic_data = (uint16_t*)(&sic_buffer[0][((int16_t)len_acc)]); + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,4,subframe,symbol); + + if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { + amp_tmp=0x1fff;//dlsch0->sqrt_rho_b; already taken into account + if (frame_parms->mode1_flag==0) + len = nb_rb*8 - (2*pbch_pss_sss_adjust/3); + else + len = nb_rb*10 - (5*pbch_pss_sss_adjust/6); + } else { + amp_tmp=0x1fff;;//dlsch0->sqrt_rho_a; already taken into account + len = nb_rb*12 - pbch_pss_sss_adjust; + } + + if (mod_order_0==6) + amp_tmp=amp_tmp<<1; // to compensate for >> 1 shift in modulation + + len_acc+=len; + + multadd_complex_vector_real_scalar((int16_t *)sic_data, + amp_tmp, + (int16_t *)rho_amp_x0, //this is in Q13 + 1, + len); + + mult_cpx_vector((int16_t *)rho_1, //Q15 + (int16_t *)rho_amp_x0, //Q13 + (int16_t*)rho_rho_amp_x0, + len, + 13); + + sub_cpx_vector16((int16_t *)rxF, + (int16_t *)rho_rho_amp_x0, + //(int16_t *)clean_x1, + (int16_t *)rxF, + len*2); + + len_mod4 = len&3; + len>>=2; // length in quad words (4 REs) + len+=(len_mod4==0 ? 0 : 1); + + for (i=0; i<len; i++) { + + + __m128i *x1 = (__m128i*)rxF;//clean_x1; +//printf("%p %p %p\n", clean_x1, &clean_x1, &clean_x1[0]); +//int *a = malloc(10*sizeof(int)); +//printf("%p %p\n", a, &a); +//exit(0); + xmm0 = _mm_abs_epi16(x1[i]); + xmm0 = _mm_subs_epi16(ch_mag[i],xmm0); + + // lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2 + llr128[0] = _mm_unpacklo_epi32(x1[i],xmm0); + llr128[1] = _mm_unpackhi_epi32(x1[i],xmm0); + llr32[0] = _mm_extract_epi32(llr128[0],0); //((uint32_t *)&llr128[0])[0]; + llr32[1] = _mm_extract_epi32(llr128[0],1); //((uint32_t *)&llr128[0])[1]; + llr32[2] = _mm_extract_epi32(llr128[0],2); //((uint32_t *)&llr128[0])[2]; + llr32[3] = _mm_extract_epi32(llr128[0],3); //((uint32_t *)&llr128[0])[3]; + llr32[4] = _mm_extract_epi32(llr128[1],0); //((uint32_t *)&llr128[1])[0]; + llr32[5] = _mm_extract_epi32(llr128[1],1); //((uint32_t *)&llr128[1])[1]; + llr32[6] = _mm_extract_epi32(llr128[1],2); //((uint32_t *)&llr128[1])[2]; + llr32[7] = _mm_extract_epi32(llr128[1],3); //((uint32_t *)&llr128[1])[3]; + llr32+=8; + + } + _mm_empty(); + _m_empty(); +} +} + //---------------------------------------------------------------------------------------------- // 64-QAM //---------------------------------------------------------------------------------------------- @@ -893,7 +1115,7 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, llr2[4] = ((short *)&xmm2)[j]; llr2[5] = ((short *)&xmm2)[j+1]; - llr2+=6; + llr2+=6; } */ llr2[0] = ((short *)&rxF[i])[0]; @@ -964,7 +1186,159 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, #endif } +//#if 0 +void dlsch_64qam_llr_SIC(LTE_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **sic_buffer, //Q15 + int32_t **rho_i, + int16_t *dlsch_llr, + uint8_t num_pdcch_symbols, + int32_t **dl_ch_mag, + int32_t **dl_ch_magb, + uint16_t nb_rb, + uint8_t subframe, + uint32_t rb_alloc, + uint16_t mod_order_0, + LTE_UE_DLSCH_t *dlsch0 + ) +{ + int16_t rho_amp_x0[2*frame_parms->N_RB_DL*12]; + int16_t rho_rho_amp_x0[2*frame_parms->N_RB_DL*12]; + uint16_t amp_tmp; + uint16_t *llr32=(uint16_t*)dlsch_llr; + int i, len, nsymb, len2; + uint8_t symbol, symbol_mod; + int len_acc=0; + uint16_t *sic_data; + uint16_t pbch_pss_sss_adjust; + unsigned char len_mod4=0; + uint16_t *llr2; + __m128i *ch_mag,*ch_magb; + + nsymb = (frame_parms->Ncp==0) ? 14:12; + + for (symbol=num_pdcch_symbols; symbol<nsymb; symbol++) { + uint16_t *rxF = (uint16_t*)(&rxdataF_comp[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + int16_t *rho_1=(int16_t*)(&rho_i[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + ch_mag = (__m128i*)(&dl_ch_mag[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + ch_magb = (__m128i*)(&dl_ch_magb[0][((int16_t)symbol*frame_parms->N_RB_DL*12)]); + sic_data = (uint16_t*)(&sic_buffer[0][((int16_t)len_acc)]); + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,6,subframe,symbol); + + if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { + amp_tmp = 0x1fff;//dlsch0->sqrt_rho_b; already taken into account + if (frame_parms->mode1_flag==0) + len = nb_rb*8 - (2*pbch_pss_sss_adjust/3); + else + len = nb_rb*10 - (5*pbch_pss_sss_adjust/6); + } else { + amp_tmp = 0x1fff; //dlsch0->sqrt_rho_a; already taken into account + len = nb_rb*12 - pbch_pss_sss_adjust; + } + + if (mod_order_0==6) + amp_tmp=amp_tmp<<1; // to compensate for >> 1 shift in modulation + + len_acc+=len; + + multadd_complex_vector_real_scalar((int16_t *)sic_data, + amp_tmp, + (int16_t *)rho_amp_x0, //this is in Q13 + 1, + len); + + mult_cpx_vector((int16_t *)rho_1, //Q15 + (int16_t *)rho_amp_x0, //Q13 + (int16_t*)rho_rho_amp_x0, + len, + 13); + + sub_cpx_vector16((int16_t *)rxF, + (int16_t *)rho_rho_amp_x0, + //(int16_t *)clean_x1, + (int16_t *)rxF, + len*2); + + llr2 = llr32; + llr32 += (len*6); + + len_mod4 =len&3; + len2=len>>2; // length in quad words (4 REs) + len2+=(len_mod4?0:1); + + + + for (i=0; i<len2; i++) { + + __m128i *x1 = (__m128i*)rxF; + xmm1 = _mm_abs_epi16(x1[i]); + xmm1 = _mm_subs_epi16(ch_mag[i],xmm1); + xmm2 = _mm_abs_epi16(xmm1); + xmm2 = _mm_subs_epi16(ch_magb[i],xmm2); + + // loop over all LLRs in quad word (24 coded bits) + /* + for (j=0;j<8;j+=2) { + llr2[0] = ((short *)&rxF[i])[j]; + llr2[1] = ((short *)&rxF[i])[j+1]; + llr2[2] = ((short *)&xmm1)[j]; + llr2[3] = ((short *)&xmm1)[j+1]; + llr2[4] = ((short *)&xmm2)[j]; + llr2[5] = ((short *)&xmm2)[j+1]; + + llr2+=6; + } + */ + llr2[0] = ((short *)&x1[i])[0]; + llr2[1] = ((short *)&x1[i])[1]; + llr2[2] = _mm_extract_epi16(xmm1,0); + llr2[3] = _mm_extract_epi16(xmm1,1);//((short *)&xmm1)[j+1]; + llr2[4] = _mm_extract_epi16(xmm2,0);//((short *)&xmm2)[j]; + llr2[5] = _mm_extract_epi16(xmm2,1);//((short *)&xmm2)[j+1]; + + llr2+=6; + llr2[0] = ((short *)&x1[i])[2]; + llr2[1] = ((short *)&x1[i])[3]; + + llr2[2] = _mm_extract_epi16(xmm1,2); + llr2[3] = _mm_extract_epi16(xmm1,3);//((short *)&xmm1)[j+1]; + llr2[4] = _mm_extract_epi16(xmm2,2);//((short *)&xmm2)[j]; + llr2[5] = _mm_extract_epi16(xmm2,3);//((short *)&xmm2)[j+1]; + + llr2+=6; + llr2[0] = ((short *)&x1[i])[4]; + llr2[1] = ((short *)&x1[i])[5]; + + llr2[2] = _mm_extract_epi16(xmm1,4); + llr2[3] = _mm_extract_epi16(xmm1,5);//((short *)&xmm1)[j+1]; + llr2[4] = _mm_extract_epi16(xmm2,4);//((short *)&xmm2)[j]; + llr2[5] = _mm_extract_epi16(xmm2,5);//((short *)&xmm2)[j+1]; + + llr2+=6; + llr2[0] = ((short *)&x1[i])[6]; + llr2[1] = ((short *)&x1[i])[7]; + + llr2[2] = _mm_extract_epi16(xmm1,6); + llr2[3] = _mm_extract_epi16(xmm1,7);//((short *)&xmm1)[j+1]; + llr2[4] = _mm_extract_epi16(xmm2,6);//((short *)&xmm2)[j]; + llr2[5] = _mm_extract_epi16(xmm2,7);//((short *)&xmm2)[j+1]; + + llr2+=6; + + } + + // *llr_save = llr; + + _mm_empty(); + _m_empty(); + + } +} +//#endif //============================================================================================== // DUAL-STREAM //============================================================================================== @@ -1033,6 +1407,7 @@ int dlsch_qpsk_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, len = (nb_rb*12) - pbch_pss_sss_adjust; } + // printf("dlsch_qpsk_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); // printf("qpsk_qpsk: len %d, llr16 %p\n",len,llr16); qpsk_qpsk((short *)rxF, (short *)rxF_i, @@ -1053,7 +1428,7 @@ void qpsk_qpsk(short *stream0_in, short *stream0_out, short *rho01, int length - ) + ) { /* @@ -1313,7 +1688,7 @@ void qpsk_qam16(int16_t *stream0_in, int16_t *stream0_out, int16_t *rho01, int32_t length - ) + ) { /* This function computes the LLRs of stream 0 (s_0) in presence of the interfering stream 1 (s_1) assuming that both symbols are QPSK. It can be used for both MU-MIMO interference-aware receiver or for SU-MIMO receivers. @@ -1544,6 +1919,7 @@ int dlsch_qpsk_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, int len; uint8_t symbol_mod = (symbol >= (7-frame_parms->Ncp))? (symbol-(7-frame_parms->Ncp)) : symbol; + if (first_symbol_flag == 1) { llr16 = (int16_t*)dlsch_llr; } else { @@ -1597,7 +1973,7 @@ void qpsk_qam64(short *stream0_in, short *stream0_out, short *rho01, int length - ) + ) { /* @@ -1849,7 +2225,7 @@ void qam16_qpsk(short *stream0_in, short *stream0_out, short *rho01, int length - ) + ) { /* @@ -1883,7 +2259,7 @@ void qam16_qpsk(short *stream0_in, __m128i y0i_over_sqrt10; __m128i y0r_three_over_sqrt10; __m128i y0i_three_over_sqrt10; - + __m128i ch_mag_des; __m128i ch_mag_over_10; __m128i ch_mag_over_2; @@ -2319,7 +2695,6 @@ int dlsch_16qam_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, llr16 = (int16_t*)(*llr16p); } - if (!llr16) { msg("dlsch_16qam_qpsk_llr: llr is null, symbol %d\n",symbol); return(-1); @@ -2360,7 +2735,7 @@ void qam16_qam16(short *stream0_in, short *stream0_out, short *rho01, int length - ) + ) { /* @@ -2919,7 +3294,7 @@ void qam16_qam64(int16_t *stream0_in, int16_t *stream0_out, int16_t *rho01, int32_t length - ) + ) { /* @@ -2945,7 +3320,7 @@ void qam16_qam64(int16_t *stream0_in, __m128i *ch_mag_128i = (__m128i *)ch_mag; __m128i *ch_mag_128i_i = (__m128i *)ch_mag_i; - + __m128i ONE_OVER_SQRT_2 = _mm_set1_epi16(23170); // round(1/sqrt(2)*2^15) __m128i ONE_OVER_SQRT_10 = _mm_set1_epi16(20724); // round(1/sqrt(10)*2^16) __m128i THREE_OVER_SQRT_10 = _mm_set1_epi16(31086); // round(3/sqrt(10)*2^15) @@ -3595,7 +3970,7 @@ void qam64_qpsk(int16_t *stream0_in, int16_t *stream0_out, int16_t *rho01, int32_t length - ) + ) { /* @@ -3657,7 +4032,7 @@ void qam64_qpsk(int16_t *stream0_in, #elif defined(__arm__) #endif - + int i,j; for (i=0; i<length>>2; i+=2) { @@ -5118,7 +5493,7 @@ void qam64_qam16(short *stream0_in, short *stream0_out, short *rho01, int length - ) + ) { /* @@ -5181,7 +5556,7 @@ void qam64_qam16(short *stream0_in, __m128i y0i_three_over_sqrt_21; __m128i y0i_five_over_sqrt_21; __m128i y0i_seven_over_sqrt_21; - + #elif defined(__arm__) #endif @@ -6663,7 +7038,7 @@ void qam64_qam64(short *stream0_in, short *stream0_out, short *rho01, int length - ) + ) { /* @@ -6730,7 +7105,7 @@ void qam64_qam64(short *stream0_in, __m128i y0i_seven_over_sqrt_21; __m128i ch_mag_int_with_sigma2; __m128i two_ch_mag_int_with_sigma2; - __m128i three_ch_mag_int_with_sigma2; + __m128i three_ch_mag_int_with_sigma2; #elif defined(__arm__) #endif @@ -8456,6 +8831,46 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, len = (nb_rb*12) - pbch_pss_sss_adjust; } +#ifdef __AVX2__ + + // Round length up to multiple of 16 words + uint32_t len256i = ((len+16)>>4)*16; + int32_t *rxF_256i = (int32_t*) malloc16_clear(len256i*4); + int32_t *rxF_i_256i = (int32_t*) malloc16_clear(len256i*4); + int32_t *ch_mag_256i = (int32_t*) malloc16_clear(len256i*4); + int32_t *ch_mag_i_256i = (int32_t*) malloc16_clear(len256i*4); + int32_t *rho_256i = (int32_t*) malloc16_clear(len256i*4); + + memcpy(rxF_256i, rxF, len*4); + memcpy(rxF_i_256i, rxF_i, len*4); + memcpy(ch_mag_256i, ch_mag, len*4); + memcpy(ch_mag_i_256i, ch_mag_i, len*4); + memcpy(rho_256i, rho, len*4); + +#if 0 + qam64_qam16_avx2((short *)rxF_256i, + (short *)rxF_i_256i, + (short *)ch_mag_256i, + (short *)ch_mag_i_256i, + (short *)llr16, + (short *) rho_256i, + len); +#else + qam64_qam64_avx2((int32_t *)rxF_256i, + (int32_t *)rxF_i_256i, + (int32_t *)ch_mag_256i, + (int32_t *)ch_mag_i_256i, + (int16_t *)llr16, + (int32_t *) rho_256i, + len); +#endif + free16(rxF_256i, sizeof(rxF_256i)); + free16(rxF_i_256i, sizeof(rxF_i_256i)); + free16(ch_mag_256i, sizeof(ch_mag_256i)); + free16(ch_mag_i_256i, sizeof(ch_mag_i_256i)); + free16(rho_256i, sizeof(rho_256i)); + +#else qam64_qam64((short *)rxF, (short *)rxF_i, (short *)ch_mag, @@ -8463,6 +8878,7 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, (short *)llr16, (short *)rho, len); +#endif llr16 += (6*len); *llr16p = (short *)llr16; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation_avx2.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation_avx2.c new file mode 100644 index 0000000000000000000000000000000000000000..cda5ad0f55ee8afbe37bf4d3536cea17fb3ed575 --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation_avx2.c @@ -0,0 +1,4034 @@ + /* + * 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.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.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/dlsch_llr_computation.c + * \brief Top-level routines for LLR computation of the PDSCH physical channel from 36-211, V8.6 2009-03 + * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, S. Wagner, X Jiang + * \date 2011 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,ankit.bhamri@eurecom.fr,sebastien.aubert@eurecom.fr, sebastian.wagner@eurecom.fr + * \note + * \warning + */ + +#include "PHY/defs.h" +#include "PHY/TOOLS/defs.h" +#include "PHY/extern.h" +#include "defs.h" +#include "extern.h" +#include "PHY/sse_intrin.h" + +int16_t ones256[16] __attribute__ ((aligned(32))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; + +static __m256i rho_rpi __attribute__ ((aligned(32))); +static __m256i rho_rmi __attribute__ ((aligned(32))); +static __m256i rho_rpi_1_1 __attribute__ ((aligned(32))); +static __m256i rho_rpi_1_3 __attribute__ ((aligned(32))); +static __m256i rho_rpi_1_5 __attribute__ ((aligned(32))); +static __m256i rho_rpi_1_7 __attribute__ ((aligned(32))); +static __m256i rho_rpi_3_1 __attribute__ ((aligned(32))); +static __m256i rho_rpi_3_3 __attribute__ ((aligned(32))); +static __m256i rho_rpi_3_5 __attribute__ ((aligned(32))); +static __m256i rho_rpi_3_7 __attribute__ ((aligned(32))); +static __m256i rho_rpi_5_1 __attribute__ ((aligned(32))); +static __m256i rho_rpi_5_3 __attribute__ ((aligned(32))); +static __m256i rho_rpi_5_5 __attribute__ ((aligned(32))); +static __m256i rho_rpi_5_7 __attribute__ ((aligned(32))); +static __m256i rho_rpi_7_1 __attribute__ ((aligned(32))); +static __m256i rho_rpi_7_3 __attribute__ ((aligned(32))); +static __m256i rho_rpi_7_5 __attribute__ ((aligned(32))); +static __m256i rho_rpi_7_7 __attribute__ ((aligned(32))); +static __m256i rho_rmi_1_1 __attribute__ ((aligned(32))); +static __m256i rho_rmi_1_3 __attribute__ ((aligned(32))); +static __m256i rho_rmi_1_5 __attribute__ ((aligned(32))); +static __m256i rho_rmi_1_7 __attribute__ ((aligned(32))); +static __m256i rho_rmi_3_1 __attribute__ ((aligned(32))); +static __m256i rho_rmi_3_3 __attribute__ ((aligned(32))); +static __m256i rho_rmi_3_5 __attribute__ ((aligned(32))); +static __m256i rho_rmi_3_7 __attribute__ ((aligned(32))); +static __m256i rho_rmi_5_1 __attribute__ ((aligned(32))); +static __m256i rho_rmi_5_3 __attribute__ ((aligned(32))); +static __m256i rho_rmi_5_5 __attribute__ ((aligned(32))); +static __m256i rho_rmi_5_7 __attribute__ ((aligned(32))); +static __m256i rho_rmi_7_1 __attribute__ ((aligned(32))); +static __m256i rho_rmi_7_3 __attribute__ ((aligned(32))); +static __m256i rho_rmi_7_5 __attribute__ ((aligned(32))); +static __m256i rho_rmi_7_7 __attribute__ ((aligned(32))); + +static __m256i psi_r_m7_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_m7_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_m5_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_m3_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_m1_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_p1_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_p3_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_p5_p7 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_m7 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_m5 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_m3 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_m1 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_p1 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_p3 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_p5 __attribute__ ((aligned(32))); +static __m256i psi_r_p7_p7 __attribute__ ((aligned(32))); + +static __m256i psi_i_m7_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_m7_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_m5_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_m3_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_m1_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_p1_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_p3_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_p5_p7 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_m7 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_m5 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_m3 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_m1 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_p1 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_p3 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_p5 __attribute__ ((aligned(32))); +static __m256i psi_i_p7_p7 __attribute__ ((aligned(32))); + +static __m256i a_r_m7_m7 __attribute__ ((aligned(32))); +static __m256i a_r_m7_m5 __attribute__ ((aligned(32))); +static __m256i a_r_m7_m3 __attribute__ ((aligned(32))); +static __m256i a_r_m7_m1 __attribute__ ((aligned(32))); +static __m256i a_r_m7_p1 __attribute__ ((aligned(32))); +static __m256i a_r_m7_p3 __attribute__ ((aligned(32))); +static __m256i a_r_m7_p5 __attribute__ ((aligned(32))); +static __m256i a_r_m7_p7 __attribute__ ((aligned(32))); +static __m256i a_r_m5_m7 __attribute__ ((aligned(32))); +static __m256i a_r_m5_m5 __attribute__ ((aligned(32))); +static __m256i a_r_m5_m3 __attribute__ ((aligned(32))); +static __m256i a_r_m5_m1 __attribute__ ((aligned(32))); +static __m256i a_r_m5_p1 __attribute__ ((aligned(32))); +static __m256i a_r_m5_p3 __attribute__ ((aligned(32))); +static __m256i a_r_m5_p5 __attribute__ ((aligned(32))); +static __m256i a_r_m5_p7 __attribute__ ((aligned(32))); +static __m256i a_r_m3_m7 __attribute__ ((aligned(32))); +static __m256i a_r_m3_m5 __attribute__ ((aligned(32))); +static __m256i a_r_m3_m3 __attribute__ ((aligned(32))); +static __m256i a_r_m3_m1 __attribute__ ((aligned(32))); +static __m256i a_r_m3_p1 __attribute__ ((aligned(32))); +static __m256i a_r_m3_p3 __attribute__ ((aligned(32))); +static __m256i a_r_m3_p5 __attribute__ ((aligned(32))); +static __m256i a_r_m3_p7 __attribute__ ((aligned(32))); +static __m256i a_r_m1_m7 __attribute__ ((aligned(32))); +static __m256i a_r_m1_m5 __attribute__ ((aligned(32))); +static __m256i a_r_m1_m3 __attribute__ ((aligned(32))); +static __m256i a_r_m1_m1 __attribute__ ((aligned(32))); +static __m256i a_r_m1_p1 __attribute__ ((aligned(32))); +static __m256i a_r_m1_p3 __attribute__ ((aligned(32))); +static __m256i a_r_m1_p5 __attribute__ ((aligned(32))); +static __m256i a_r_m1_p7 __attribute__ ((aligned(32))); +static __m256i a_r_p1_m7 __attribute__ ((aligned(32))); +static __m256i a_r_p1_m5 __attribute__ ((aligned(32))); +static __m256i a_r_p1_m3 __attribute__ ((aligned(32))); +static __m256i a_r_p1_m1 __attribute__ ((aligned(32))); +static __m256i a_r_p1_p1 __attribute__ ((aligned(32))); +static __m256i a_r_p1_p3 __attribute__ ((aligned(32))); +static __m256i a_r_p1_p5 __attribute__ ((aligned(32))); +static __m256i a_r_p1_p7 __attribute__ ((aligned(32))); +static __m256i a_r_p3_m7 __attribute__ ((aligned(32))); +static __m256i a_r_p3_m5 __attribute__ ((aligned(32))); +static __m256i a_r_p3_m3 __attribute__ ((aligned(32))); +static __m256i a_r_p3_m1 __attribute__ ((aligned(32))); +static __m256i a_r_p3_p1 __attribute__ ((aligned(32))); +static __m256i a_r_p3_p3 __attribute__ ((aligned(32))); +static __m256i a_r_p3_p5 __attribute__ ((aligned(32))); +static __m256i a_r_p3_p7 __attribute__ ((aligned(32))); +static __m256i a_r_p5_m7 __attribute__ ((aligned(32))); +static __m256i a_r_p5_m5 __attribute__ ((aligned(32))); +static __m256i a_r_p5_m3 __attribute__ ((aligned(32))); +static __m256i a_r_p5_m1 __attribute__ ((aligned(32))); +static __m256i a_r_p5_p1 __attribute__ ((aligned(32))); +static __m256i a_r_p5_p3 __attribute__ ((aligned(32))); +static __m256i a_r_p5_p5 __attribute__ ((aligned(32))); +static __m256i a_r_p5_p7 __attribute__ ((aligned(32))); +static __m256i a_r_p7_m7 __attribute__ ((aligned(32))); +static __m256i a_r_p7_m5 __attribute__ ((aligned(32))); +static __m256i a_r_p7_m3 __attribute__ ((aligned(32))); +static __m256i a_r_p7_m1 __attribute__ ((aligned(32))); +static __m256i a_r_p7_p1 __attribute__ ((aligned(32))); +static __m256i a_r_p7_p3 __attribute__ ((aligned(32))); +static __m256i a_r_p7_p5 __attribute__ ((aligned(32))); +static __m256i a_r_p7_p7 __attribute__ ((aligned(32))); + +static __m256i a_i_m7_m7 __attribute__ ((aligned(32))); +static __m256i a_i_m7_m5 __attribute__ ((aligned(32))); +static __m256i a_i_m7_m3 __attribute__ ((aligned(32))); +static __m256i a_i_m7_m1 __attribute__ ((aligned(32))); +static __m256i a_i_m7_p1 __attribute__ ((aligned(32))); +static __m256i a_i_m7_p3 __attribute__ ((aligned(32))); +static __m256i a_i_m7_p5 __attribute__ ((aligned(32))); +static __m256i a_i_m7_p7 __attribute__ ((aligned(32))); +static __m256i a_i_m5_m7 __attribute__ ((aligned(32))); +static __m256i a_i_m5_m5 __attribute__ ((aligned(32))); +static __m256i a_i_m5_m3 __attribute__ ((aligned(32))); +static __m256i a_i_m5_m1 __attribute__ ((aligned(32))); +static __m256i a_i_m5_p1 __attribute__ ((aligned(32))); +static __m256i a_i_m5_p3 __attribute__ ((aligned(32))); +static __m256i a_i_m5_p5 __attribute__ ((aligned(32))); +static __m256i a_i_m5_p7 __attribute__ ((aligned(32))); +static __m256i a_i_m3_m7 __attribute__ ((aligned(32))); +static __m256i a_i_m3_m5 __attribute__ ((aligned(32))); +static __m256i a_i_m3_m3 __attribute__ ((aligned(32))); +static __m256i a_i_m3_m1 __attribute__ ((aligned(32))); +static __m256i a_i_m3_p1 __attribute__ ((aligned(32))); +static __m256i a_i_m3_p3 __attribute__ ((aligned(32))); +static __m256i a_i_m3_p5 __attribute__ ((aligned(32))); +static __m256i a_i_m3_p7 __attribute__ ((aligned(32))); +static __m256i a_i_m1_m7 __attribute__ ((aligned(32))); +static __m256i a_i_m1_m5 __attribute__ ((aligned(32))); +static __m256i a_i_m1_m3 __attribute__ ((aligned(32))); +static __m256i a_i_m1_m1 __attribute__ ((aligned(32))); +static __m256i a_i_m1_p1 __attribute__ ((aligned(32))); +static __m256i a_i_m1_p3 __attribute__ ((aligned(32))); +static __m256i a_i_m1_p5 __attribute__ ((aligned(32))); +static __m256i a_i_m1_p7 __attribute__ ((aligned(32))); +static __m256i a_i_p1_m7 __attribute__ ((aligned(32))); +static __m256i a_i_p1_m5 __attribute__ ((aligned(32))); +static __m256i a_i_p1_m3 __attribute__ ((aligned(32))); +static __m256i a_i_p1_m1 __attribute__ ((aligned(32))); +static __m256i a_i_p1_p1 __attribute__ ((aligned(32))); +static __m256i a_i_p1_p3 __attribute__ ((aligned(32))); +static __m256i a_i_p1_p5 __attribute__ ((aligned(32))); +static __m256i a_i_p1_p7 __attribute__ ((aligned(32))); +static __m256i a_i_p3_m7 __attribute__ ((aligned(32))); +static __m256i a_i_p3_m5 __attribute__ ((aligned(32))); +static __m256i a_i_p3_m3 __attribute__ ((aligned(32))); +static __m256i a_i_p3_m1 __attribute__ ((aligned(32))); +static __m256i a_i_p3_p1 __attribute__ ((aligned(32))); +static __m256i a_i_p3_p3 __attribute__ ((aligned(32))); +static __m256i a_i_p3_p5 __attribute__ ((aligned(32))); +static __m256i a_i_p3_p7 __attribute__ ((aligned(32))); +static __m256i a_i_p5_m7 __attribute__ ((aligned(32))); +static __m256i a_i_p5_m5 __attribute__ ((aligned(32))); +static __m256i a_i_p5_m3 __attribute__ ((aligned(32))); +static __m256i a_i_p5_m1 __attribute__ ((aligned(32))); +static __m256i a_i_p5_p1 __attribute__ ((aligned(32))); +static __m256i a_i_p5_p3 __attribute__ ((aligned(32))); +static __m256i a_i_p5_p5 __attribute__ ((aligned(32))); +static __m256i a_i_p5_p7 __attribute__ ((aligned(32))); +static __m256i a_i_p7_m7 __attribute__ ((aligned(32))); +static __m256i a_i_p7_m5 __attribute__ ((aligned(32))); +static __m256i a_i_p7_m3 __attribute__ ((aligned(32))); +static __m256i a_i_p7_m1 __attribute__ ((aligned(32))); +static __m256i a_i_p7_p1 __attribute__ ((aligned(32))); +static __m256i a_i_p7_p3 __attribute__ ((aligned(32))); +static __m256i a_i_p7_p5 __attribute__ ((aligned(32))); +static __m256i a_i_p7_p7 __attribute__ ((aligned(32))); + +static __m256i psi_a_m7_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_m7_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_m5_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_m3_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_m1_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_p1_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_p3_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_p5_p7 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_m7 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_m5 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_m3 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_m1 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_p1 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_p3 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_p5 __attribute__ ((aligned(32))); +static __m256i psi_a_p7_p7 __attribute__ ((aligned(32))); + +static __m256i a_sq_m7_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_m7_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_m5_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_m3_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_m1_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_p1_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_p3_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_p5_p7 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_m7 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_m5 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_m3 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_m1 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_p1 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_p3 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_p5 __attribute__ ((aligned(32))); +static __m256i a_sq_p7_p7 __attribute__ ((aligned(32))); + +static __m256i bit_met_m7_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_m7_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_m5_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_m3_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_m1_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_p1_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_p3_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_p5_p7 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_m7 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_m5 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_m3 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_m1 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_p1 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_p3 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_p5 __attribute__ ((aligned(32))); +static __m256i bit_met_p7_p7 __attribute__ ((aligned(32))); + +static __m256i y0_p_1_1 __attribute__ ((aligned(32))); +static __m256i y0_p_1_3 __attribute__ ((aligned(32))); +static __m256i y0_p_1_5 __attribute__ ((aligned(32))); +static __m256i y0_p_1_7 __attribute__ ((aligned(32))); +static __m256i y0_p_3_1 __attribute__ ((aligned(32))); +static __m256i y0_p_3_3 __attribute__ ((aligned(32))); +static __m256i y0_p_3_5 __attribute__ ((aligned(32))); +static __m256i y0_p_3_7 __attribute__ ((aligned(32))); +static __m256i y0_p_5_1 __attribute__ ((aligned(32))); +static __m256i y0_p_5_3 __attribute__ ((aligned(32))); +static __m256i y0_p_5_5 __attribute__ ((aligned(32))); +static __m256i y0_p_5_7 __attribute__ ((aligned(32))); +static __m256i y0_p_7_1 __attribute__ ((aligned(32))); +static __m256i y0_p_7_3 __attribute__ ((aligned(32))); +static __m256i y0_p_7_5 __attribute__ ((aligned(32))); +static __m256i y0_p_7_7 __attribute__ ((aligned(32))); +static __m256i y0_m_1_1 __attribute__ ((aligned(32))); +static __m256i y0_m_1_3 __attribute__ ((aligned(32))); +static __m256i y0_m_1_5 __attribute__ ((aligned(32))); +static __m256i y0_m_1_7 __attribute__ ((aligned(32))); +static __m256i y0_m_3_1 __attribute__ ((aligned(32))); +static __m256i y0_m_3_3 __attribute__ ((aligned(32))); +static __m256i y0_m_3_5 __attribute__ ((aligned(32))); +static __m256i y0_m_3_7 __attribute__ ((aligned(32))); +static __m256i y0_m_5_1 __attribute__ ((aligned(32))); +static __m256i y0_m_5_3 __attribute__ ((aligned(32))); +static __m256i y0_m_5_5 __attribute__ ((aligned(32))); +static __m256i y0_m_5_7 __attribute__ ((aligned(32))); +static __m256i y0_m_7_1 __attribute__ ((aligned(32))); +static __m256i y0_m_7_3 __attribute__ ((aligned(32))); +static __m256i y0_m_7_5 __attribute__ ((aligned(32))); +static __m256i y0_m_7_7 __attribute__ ((aligned(32))); + +static __m256i xmm0 __attribute__ ((aligned(32))); +static __m256i xmm1 __attribute__ ((aligned(32))); +static __m256i xmm2 __attribute__ ((aligned(32))); +static __m256i xmm3 __attribute__ ((aligned(32))); +static __m256i xmm4 __attribute__ ((aligned(32))); +static __m256i xmm5 __attribute__ ((aligned(32))); +static __m256i xmm6 __attribute__ ((aligned(32))); +static __m256i xmm7 __attribute__ ((aligned(32))); +static __m256i xmm8 __attribute__ ((aligned(32))); + +static __m256i y0r __attribute__ ((aligned(32))); +static __m256i y0i __attribute__ ((aligned(32))); +static __m256i y1r __attribute__ ((aligned(32))); +static __m256i y1i __attribute__ ((aligned(32))); +static __m256i y2r __attribute__ ((aligned(32))); +static __m256i y2i __attribute__ ((aligned(32))); + +static __m256i logmax_num_re0 __attribute__ ((aligned(32))); +static __m256i logmax_den_re0 __attribute__ ((aligned(32))); + +static __m256i tmp_result __attribute__ ((aligned(32))); +static __m256i tmp_result2 __attribute__ ((aligned(32))); +static __m256i tmp_result3 __attribute__ ((aligned(32))); +static __m256i tmp_result4 __attribute__ ((aligned(32))); + +//============================================================================================== +// Auxiliary Makros + +// calculate interference magnitude +#define interference_abs_epi16(psi,int_ch_mag,int_mag,c1,c2) tmp_result = _mm256_cmpgt_epi16(int_ch_mag,psi); tmp_result2 = _mm256_xor_si256(tmp_result,(*(__m256i*)&ones256[0])); tmp_result = _mm256_and_si256(tmp_result,c1); tmp_result2 = _mm256_and_si256(tmp_result2,c2); int_mag = _mm256_or_si256(tmp_result,tmp_result2); + +// calculate interference magnitude +// tmp_result = ones in shorts corr. to interval 2<=x<=4, tmp_result2 interval < 2, tmp_result3 interval 4<x<6 and tmp_result4 interval x>6 +#define interference_abs_64qam_epi16(psi,int_ch_mag,int_two_ch_mag,int_three_ch_mag,a,c1,c3,c5,c7) tmp_result = _mm256_cmpgt_epi16(int_two_ch_mag,psi); tmp_result3 = _mm256_xor_si256(tmp_result,(*(__m256i*)&ones256[0])); tmp_result2 = _mm256_cmpgt_epi16(int_ch_mag,psi); tmp_result = _mm256_xor_si256(tmp_result,tmp_result2); tmp_result4 = _mm256_cmpgt_epi16(psi,int_three_ch_mag); tmp_result3 = _mm256_xor_si256(tmp_result3,tmp_result4); tmp_result = _mm256_and_si256(tmp_result,c3); tmp_result2 = _mm256_and_si256(tmp_result2,c1); tmp_result3 = _mm256_and_si256(tmp_result3,c5); tmp_result4 = _mm256_and_si256(tmp_result4,c7); tmp_result = _mm256_or_si256(tmp_result,tmp_result2); tmp_result3 = _mm256_or_si256(tmp_result3,tmp_result4); a = _mm256_or_si256(tmp_result,tmp_result3); + +// calculates psi_a = psi_r*a_r + psi_i*a_i +#define prodsum_psi_a_epi16(psi_r,a_r,psi_i,a_i,psi_a) tmp_result = _mm256_mulhi_epi16(psi_r,a_r); tmp_result = _mm256_slli_epi16(tmp_result,1); tmp_result2 = _mm256_mulhi_epi16(psi_i,a_i); tmp_result2 = _mm256_slli_epi16(tmp_result2,1); psi_a = _mm256_adds_epi16(tmp_result,tmp_result2); + +// calculates a_sq = int_ch_mag*(a_r^2 + a_i^2)*scale_factor +#define square_a_epi16(a_r,a_i,int_ch_mag,scale_factor,a_sq) tmp_result = _mm256_mulhi_epi16(a_r,a_r); tmp_result = _mm256_slli_epi16(tmp_result,1); tmp_result = _mm256_mulhi_epi16(tmp_result,scale_factor); tmp_result = _mm256_slli_epi16(tmp_result,1); tmp_result = _mm256_mulhi_epi16(tmp_result,int_ch_mag); tmp_result = _mm256_slli_epi16(tmp_result,1); tmp_result2 = _mm256_mulhi_epi16(a_i,a_i); tmp_result2 = _mm256_slli_epi16(tmp_result2,1); tmp_result2 = _mm256_mulhi_epi16(tmp_result2,scale_factor); tmp_result2 = _mm256_slli_epi16(tmp_result2,1); tmp_result2 = _mm256_mulhi_epi16(tmp_result2,int_ch_mag); tmp_result2 = _mm256_slli_epi16(tmp_result2,1); a_sq = _mm256_adds_epi16(tmp_result,tmp_result2); + +// calculates a_sq = int_ch_mag*(a_r^2 + a_i^2)*scale_factor for 64-QAM +#define square_a_64qam_epi16(a_r,a_i,int_ch_mag,scale_factor,a_sq) tmp_result = _mm256_mulhi_epi16(a_r,a_r); tmp_result = _mm256_slli_epi16(tmp_result,1); tmp_result = _mm256_mulhi_epi16(tmp_result,scale_factor); tmp_result = _mm256_slli_epi16(tmp_result,3); tmp_result = _mm256_mulhi_epi16(tmp_result,int_ch_mag); tmp_result = _mm256_slli_epi16(tmp_result,1); tmp_result2 = _mm256_mulhi_epi16(a_i,a_i); tmp_result2 = _mm256_slli_epi16(tmp_result2,1); tmp_result2 = _mm256_mulhi_epi16(tmp_result2,scale_factor); tmp_result2 = _mm256_slli_epi16(tmp_result2,3); tmp_result2 = _mm256_mulhi_epi16(tmp_result2,int_ch_mag); tmp_result2 = _mm256_slli_epi16(tmp_result2,1); a_sq = _mm256_adds_epi16(tmp_result,tmp_result2); + +void seperate_real_imag_parts(__m256i *out_re, + __m256i *out_im, + __m256i in0, + __m256i in1) +{ + __m256i tmp0; + __m256i tmp1; + + in0 = _mm256_shufflelo_epi16(in0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = _mm256_shufflehi_epi16(in0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + in0 = _mm256_shuffle_epi32(in0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + + in1 = _mm256_shufflelo_epi16(in1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = _mm256_shufflehi_epi16(in1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + in1 = _mm256_shuffle_epi32(in1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + + //in0 = [Re(0,1,2,3) Im(0,1,2,3) Re(4,5,6,7) Im(4,5,6,7)] + //in0 = [Re(8,9,10,11) Im(8,9,10,11) Re(12,13,14,15) Im(12,13,14,15)] + + tmp0 = _mm256_unpacklo_epi64(in0, in1); + //axmm2 = [Re(0,1,2,3) Re(8,9,10,11) Re(4,5,6,7) Re(12,13,14,15)] + tmp0 = _mm256_permute4x64_epi64(tmp0,0xd8); // Re(rho) + + tmp1 = _mm256_unpackhi_epi64(in0, in1); + //axmm3 = [Im(0,1,2,3) Im(8,9,10,11) Im(4,5,6,7) Im(12,13,14,15)] + tmp1 = _mm256_permute4x64_epi64(tmp1,0xd8); // Im(rho) + + *out_re = tmp0; + *out_im = tmp1; +} + +void qam64_qam16_avx2(short *stream0_in, + short *stream1_in, + short *ch_mag, + short *ch_mag_i, + short *stream0_out, + short *rho01, + int length + ) +{ + + /* + Author: S. Wagner + Date: 31-07-12 + + Input: + stream0_in: MF filter for 1st stream, i.e., y0=h0'*y + stream1_in: MF filter for 2nd stream, i.e., y1=h1'*y + ch_mag: 4*h0/sqrt(42), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + ch_mag_i: 4*h1/sqrt(42), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + rho01: Channel cross correlation, i.e., h1'*h0 + + Output: + stream0_out: output LLRs for 1st stream + */ + +#if defined(__x86_64__) || defined(__i386__) + + __m256i *rho01_256i = (__m256i *)rho01; + __m256i *stream0_256i_in = (__m256i *)stream0_in; + __m256i *stream1_256i_in = (__m256i *)stream1_in; + __m256i *ch_mag_256i = (__m256i *)ch_mag; + __m256i *ch_mag_256i_i = (__m256i *)ch_mag_i; + + __m256i ONE_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(10112)); // round(1/sqrt(42)*2^16) + __m256i THREE_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(30337)); // round(3/sqrt(42)*2^16) + __m256i FIVE_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(25281)); // round(5/sqrt(42)*2^15) + __m256i SEVEN_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(17697)); // round(5/sqrt(42)*2^15) + __m256i FORTYNINE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(30969)); // round(49/(4*sqrt(42))*2^14), Q2.14 + __m256i THIRTYSEVEN_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(23385)); // round(37/(4*sqrt(42))*2^14), Q2.14 + __m256i TWENTYFIVE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(31601)); // round(25/(4*sqrt(42))*2^15) + __m256i TWENTYNINE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(18329)); // round(29/(4*sqrt(42))*2^15), Q2.14 + __m256i SEVENTEEN_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(21489)); // round(17/(4*sqrt(42))*2^15) + __m256i NINE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(11376)); // round(9/(4*sqrt(42))*2^15) + __m256i THIRTEEN_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(16433)); // round(13/(4*sqrt(42))*2^15) + __m256i FIVE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(6320)); // round(5/(4*sqrt(42))*2^15) + __m256i ONE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(1264)); // round(1/(4*sqrt(42))*2^15) + __m256i ONE_OVER_SQRT_10_Q15 = _mm256_broadcastw_epi16(_mm_set1_epi16(10362)); // round(1/sqrt(10)*2^15) + __m256i THREE_OVER_SQRT_10 = _mm256_broadcastw_epi16(_mm_set1_epi16(31086)); // round(3/sqrt(10)*2^15) + __m256i SQRT_10_OVER_FOUR = _mm256_broadcastw_epi16(_mm_set1_epi16(25905)); // round(sqrt(10)/4*2^15) + + + __m256i ch_mag_int; + __m256i ch_mag_des; + __m256i ch_mag_98_over_42_with_sigma2; + __m256i ch_mag_74_over_42_with_sigma2; + __m256i ch_mag_58_over_42_with_sigma2; + __m256i ch_mag_50_over_42_with_sigma2; + __m256i ch_mag_34_over_42_with_sigma2; + __m256i ch_mag_18_over_42_with_sigma2; + __m256i ch_mag_26_over_42_with_sigma2; + __m256i ch_mag_10_over_42_with_sigma2; + __m256i ch_mag_2_over_42_with_sigma2; + __m256i y0r_one_over_sqrt_21; + __m256i y0r_three_over_sqrt_21; + __m256i y0r_five_over_sqrt_21; + __m256i y0r_seven_over_sqrt_21; + __m256i y0i_one_over_sqrt_21; + __m256i y0i_three_over_sqrt_21; + __m256i y0i_five_over_sqrt_21; + __m256i y0i_seven_over_sqrt_21; + +#elif defined(__arm__) + +#endif + int i,j; + uint32_t len256 = (length)>>3; + + for (i=0; i<len256; i+=2) { + +#if defined(__x86_64__) || defined(__i386__) + // Get rho + /* + xmm0 = rho01_128i[i]; + xmm1 = rho01_128i[i+1]; + xmm0 = _mm_shufflelo_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm_shufflehi_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm_shuffle_epi32(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm_shufflelo_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm_shufflehi_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm_shuffle_epi32(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + //xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + //xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + xmm2 = _mm_unpacklo_epi64(xmm0,xmm1); // Re(rho) + xmm3 = _mm_unpackhi_epi64(xmm0,xmm1); // Im(rho) + */ + seperate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i+1]); + + rho_rpi = _mm256_adds_epi16(xmm2,xmm3); // rho = Re(rho) + Im(rho) + rho_rmi = _mm256_subs_epi16(xmm2,xmm3); // rho* = Re(rho) - Im(rho) + + // Compute the different rhos + rho_rpi_1_1 = _mm256_mulhi_epi16(rho_rpi, ONE_OVER_SQRT_42); + rho_rmi_1_1 = _mm256_mulhi_epi16(rho_rmi, ONE_OVER_SQRT_42); + rho_rpi_3_3 = _mm256_mulhi_epi16(rho_rpi, THREE_OVER_SQRT_42); + rho_rmi_3_3 = _mm256_mulhi_epi16(rho_rmi, THREE_OVER_SQRT_42); + rho_rpi_5_5 = _mm256_mulhi_epi16(rho_rpi, FIVE_OVER_SQRT_42); + rho_rmi_5_5 = _mm256_mulhi_epi16(rho_rmi, FIVE_OVER_SQRT_42); + rho_rpi_7_7 = _mm256_mulhi_epi16(rho_rpi, SEVEN_OVER_SQRT_42); + rho_rmi_7_7 = _mm256_mulhi_epi16(rho_rmi, SEVEN_OVER_SQRT_42); + + rho_rpi_5_5 = _mm256_slli_epi16(rho_rpi_5_5, 1); + rho_rmi_5_5 = _mm256_slli_epi16(rho_rmi_5_5, 1); + rho_rpi_7_7 = _mm256_slli_epi16(rho_rpi_7_7, 2); + rho_rmi_7_7 = _mm256_slli_epi16(rho_rmi_7_7, 2); + + xmm4 = _mm256_mulhi_epi16(xmm2, ONE_OVER_SQRT_42); + xmm5 = _mm256_mulhi_epi16(xmm3, ONE_OVER_SQRT_42); + xmm6 = _mm256_mulhi_epi16(xmm3, THREE_OVER_SQRT_42); + xmm7 = _mm256_mulhi_epi16(xmm3, FIVE_OVER_SQRT_42); + xmm8 = _mm256_mulhi_epi16(xmm3, SEVEN_OVER_SQRT_42); + xmm7 = _mm256_slli_epi16(xmm7, 1); + xmm8 = _mm256_slli_epi16(xmm8, 2); + + rho_rpi_1_3 = _mm256_adds_epi16(xmm4, xmm6); + rho_rmi_1_3 = _mm256_subs_epi16(xmm4, xmm6); + rho_rpi_1_5 = _mm256_adds_epi16(xmm4, xmm7); + rho_rmi_1_5 = _mm256_subs_epi16(xmm4, xmm7); + rho_rpi_1_7 = _mm256_adds_epi16(xmm4, xmm8); + rho_rmi_1_7 = _mm256_subs_epi16(xmm4, xmm8); + + xmm4 = _mm256_mulhi_epi16(xmm2, THREE_OVER_SQRT_42); + rho_rpi_3_1 = _mm256_adds_epi16(xmm4, xmm5); + rho_rmi_3_1 = _mm256_subs_epi16(xmm4, xmm5); + rho_rpi_3_5 = _mm256_adds_epi16(xmm4, xmm7); + rho_rmi_3_5 = _mm256_subs_epi16(xmm4, xmm7); + rho_rpi_3_7 = _mm256_adds_epi16(xmm4, xmm8); + rho_rmi_3_7 = _mm256_subs_epi16(xmm4, xmm8); + + xmm4 = _mm256_mulhi_epi16(xmm2, FIVE_OVER_SQRT_42); + xmm4 = _mm256_slli_epi16(xmm4, 1); + rho_rpi_5_1 = _mm256_adds_epi16(xmm4, xmm5); + rho_rmi_5_1 = _mm256_subs_epi16(xmm4, xmm5); + rho_rpi_5_3 = _mm256_adds_epi16(xmm4, xmm6); + rho_rmi_5_3 = _mm256_subs_epi16(xmm4, xmm6); + rho_rpi_5_7 = _mm256_adds_epi16(xmm4, xmm8); + rho_rmi_5_7 = _mm256_subs_epi16(xmm4, xmm8); + + xmm4 = _mm256_mulhi_epi16(xmm2, SEVEN_OVER_SQRT_42); + xmm4 = _mm256_slli_epi16(xmm4, 2); + rho_rpi_7_1 = _mm256_adds_epi16(xmm4, xmm5); + rho_rmi_7_1 = _mm256_subs_epi16(xmm4, xmm5); + rho_rpi_7_3 = _mm256_adds_epi16(xmm4, xmm6); + rho_rmi_7_3 = _mm256_subs_epi16(xmm4, xmm6); + rho_rpi_7_5 = _mm256_adds_epi16(xmm4, xmm7); + rho_rmi_7_5 = _mm256_subs_epi16(xmm4, xmm7); + + // Rearrange interfering MF output + /* + xmm0 = stream1_128i_in[i]; + xmm1 = stream1_128i_in[i+1]; + xmm0 = _mm256_shufflelo_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shufflehi_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shuffle_epi32(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shufflelo_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shufflehi_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shuffle_epi32(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + //xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + //xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + y1r = _mm256_unpacklo_epi64(xmm0,xmm1); //[y1r(1),y1r(2),y1r(3),y1r(4)] + y1i = _mm256_unpackhi_epi64(xmm0,xmm1); //[y1i(1),y1i(2),y1i(3),y1i(4)] + */ + + seperate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i+1]); + + // Psi_r calculation from rho_rpi or rho_rmi + xmm0 = _mm256_broadcastw_epi16(_mm_set1_epi16(0));// ZERO for abs_pi16 + xmm2 = _mm256_subs_epi16(rho_rpi_7_7, y1r); + psi_r_p7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_5, y1r); + psi_r_p7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_3, y1r); + psi_r_p7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_1, y1r); + psi_r_p7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_1, y1r); + psi_r_p7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_3, y1r); + psi_r_p7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_5, y1r); + psi_r_p7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_7, y1r); + psi_r_p7_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_7, y1r); + psi_r_p5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_5, y1r); + psi_r_p5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_3, y1r); + psi_r_p5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_1, y1r); + psi_r_p5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_1, y1r); + psi_r_p5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_3, y1r); + psi_r_p5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_5, y1r); + psi_r_p5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_7, y1r); + psi_r_p5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_7, y1r); + psi_r_p3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_5, y1r); + psi_r_p3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_3, y1r); + psi_r_p3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_1, y1r); + psi_r_p3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_1, y1r); + psi_r_p3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_3, y1r); + psi_r_p3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_5, y1r); + psi_r_p3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_7, y1r); + psi_r_p3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_7, y1r); + psi_r_p1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_5, y1r); + psi_r_p1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_3, y1r); + psi_r_p1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_1, y1r); + psi_r_p1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_1, y1r); + psi_r_p1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_3, y1r); + psi_r_p1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_5, y1r); + psi_r_p1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_7, y1r); + psi_r_p1_m7 = _mm256_abs_epi16(xmm2); + + xmm2 = _mm256_adds_epi16(rho_rmi_1_7, y1r); + psi_r_m1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_5, y1r); + psi_r_m1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_3, y1r); + psi_r_m1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_1, y1r); + psi_r_m1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_1, y1r); + psi_r_m1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_3, y1r); + psi_r_m1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_5, y1r); + psi_r_m1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_7, y1r); + psi_r_m1_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_7, y1r); + psi_r_m3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_5, y1r); + psi_r_m3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_3, y1r); + psi_r_m3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_1, y1r); + psi_r_m3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_1, y1r); + psi_r_m3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_3, y1r); + psi_r_m3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_5, y1r); + psi_r_m3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_7, y1r); + psi_r_m3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_7, y1r); + psi_r_m5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_5, y1r); + psi_r_m5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_3, y1r); + psi_r_m5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_1, y1r); + psi_r_m5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_1, y1r); + psi_r_m5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_3, y1r); + psi_r_m5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_5, y1r); + psi_r_m5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_7, y1r); + psi_r_m5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_7, y1r); + psi_r_m7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_5, y1r); + psi_r_m7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_3, y1r); + psi_r_m7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_1, y1r); + psi_r_m7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_1, y1r); + psi_r_m7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_3, y1r); + psi_r_m7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_5, y1r); + psi_r_m7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_7, y1r); + psi_r_m7_m7 = _mm256_abs_epi16(xmm2); + + // Psi_i calculation from rho_rpi or rho_rmi + xmm2 = _mm256_subs_epi16(rho_rmi_7_7, y1i); + psi_i_p7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_7, y1i); + psi_i_p7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_7, y1i); + psi_i_p7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_7, y1i); + psi_i_p7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_7, y1i); + psi_i_p7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_7, y1i); + psi_i_p7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_7, y1i); + psi_i_p7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_7, y1i); + psi_i_p7_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_5, y1i); + psi_i_p5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_5, y1i); + psi_i_p5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_5, y1i); + psi_i_p5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_5, y1i); + psi_i_p5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_5, y1i); + psi_i_p5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_5, y1i); + psi_i_p5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_5, y1i); + psi_i_p5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_5, y1i); + psi_i_p5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_3, y1i); + psi_i_p3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_3, y1i); + psi_i_p3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_3, y1i); + psi_i_p3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_3, y1i); + psi_i_p3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_3, y1i); + psi_i_p3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_3, y1i); + psi_i_p3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_3, y1i); + psi_i_p3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_3, y1i); + psi_i_p3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_1, y1i); + psi_i_p1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_1, y1i); + psi_i_p1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_1, y1i); + psi_i_p1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_1, y1i); + psi_i_p1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_1, y1i); + psi_i_p1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_1, y1i); + psi_i_p1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_1, y1i); + psi_i_p1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_1, y1i); + psi_i_p1_m7 = _mm256_abs_epi16(xmm2); + + xmm2 = _mm256_subs_epi16(rho_rpi_7_1, y1i); + psi_i_m1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_1, y1i); + psi_i_m1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_1, y1i); + psi_i_m1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_1, y1i); + psi_i_m1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_1, y1i); + psi_i_m1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_1, y1i); + psi_i_m1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_1, y1i); + psi_i_m1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_1, y1i); + psi_i_m1_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_3, y1i); + psi_i_m3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_3, y1i); + psi_i_m3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_3, y1i); + psi_i_m3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_3, y1i); + psi_i_m3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_3, y1i); + psi_i_m3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_3, y1i); + psi_i_m3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_3, y1i); + psi_i_m3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_3, y1i); + psi_i_m3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_5, y1i); + psi_i_m5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_5, y1i); + psi_i_m5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_5, y1i); + psi_i_m5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_5, y1i); + psi_i_m5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_5, y1i); + psi_i_m5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_5, y1i); + psi_i_m5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_5, y1i); + psi_i_m5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_5, y1i); + psi_i_m5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_7, y1i); + psi_i_m7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_7, y1i); + psi_i_m7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_7, y1i); + psi_i_m7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_7, y1i); + psi_i_m7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_7, y1i); + psi_i_m7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_7, y1i); + psi_i_m7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_7, y1i); + psi_i_m7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_7, y1i); + psi_i_m7_m7 = _mm256_abs_epi16(xmm2); + +/* + // Rearrange desired MF output + xmm0 = stream0_128i_in[i]; + xmm1 = stream0_128i_in[i+1]; + xmm0 = _mm256_shufflelo_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shufflehi_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shuffle_epi32(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shufflelo_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shufflehi_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shuffle_epi32(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + //xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + //xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + y0r = _mm256_unpacklo_epi64(xmm0,xmm1); // = [y0r(1),y0r(2),y0r(3),y0r(4)] + y0i = _mm256_unpackhi_epi64(xmm0,xmm1); +*/ + seperate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i+1]); + + /* + // Rearrange desired channel magnitudes + xmm2 = ch_mag_128i[i]; // = [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2)]*(2/sqrt(10)) + xmm3 = ch_mag_128i[i+1]; // = [|h|^2(3),|h|^2(3),|h|^2(4),|h|^2(4)]*(2/sqrt(10)) + xmm2 = _mm256_shufflelo_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm256_shufflehi_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm256_shuffle_epi32(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm256_shufflelo_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm256_shufflehi_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm256_shuffle_epi32(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + ch_mag_des = _mm256_unpacklo_epi64(xmm2,xmm3); + */ + + seperate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i+1]); + + // Rearrange interfering channel magnitudes + /* + xmm2 = ch_mag_128i_i[i]; + xmm3 = ch_mag_128i_i[i+1]; + xmm2 = _mm256_shufflelo_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm256_shufflehi_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm256_shuffle_epi32(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm256_shufflelo_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm256_shufflehi_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm256_shuffle_epi32(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + ch_mag_int = _mm256_unpacklo_epi64(xmm2,xmm3); + */ + + seperate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i+1]); + + y0r_one_over_sqrt_21 = _mm256_mulhi_epi16(y0r, ONE_OVER_SQRT_42); + y0r_three_over_sqrt_21 = _mm256_mulhi_epi16(y0r, THREE_OVER_SQRT_42); + y0r_five_over_sqrt_21 = _mm256_mulhi_epi16(y0r, FIVE_OVER_SQRT_42); + y0r_five_over_sqrt_21 = _mm256_slli_epi16(y0r_five_over_sqrt_21, 1); + y0r_seven_over_sqrt_21 = _mm256_mulhi_epi16(y0r, SEVEN_OVER_SQRT_42); + y0r_seven_over_sqrt_21 = _mm256_slli_epi16(y0r_seven_over_sqrt_21, 2); // Q2.14 + + y0i_one_over_sqrt_21 = _mm256_mulhi_epi16(y0i, ONE_OVER_SQRT_42); + y0i_three_over_sqrt_21 = _mm256_mulhi_epi16(y0i, THREE_OVER_SQRT_42); + y0i_five_over_sqrt_21 = _mm256_mulhi_epi16(y0i, FIVE_OVER_SQRT_42); + y0i_five_over_sqrt_21 = _mm256_slli_epi16(y0i_five_over_sqrt_21, 1); + y0i_seven_over_sqrt_21 = _mm256_mulhi_epi16(y0i, SEVEN_OVER_SQRT_42); + y0i_seven_over_sqrt_21 = _mm256_slli_epi16(y0i_seven_over_sqrt_21, 2); // Q2.14 + + y0_p_7_1 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_7_3 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_7_5 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_7_7 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_p_5_1 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_5_3 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_5_5 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_5_7 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_p_3_1 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_3_3 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_3_5 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_3_7 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_p_1_1 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_1_3 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_1_5 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_1_7 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_seven_over_sqrt_21); + + y0_m_1_1 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_1_3 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_1_5 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_1_7 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_m_3_1 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_3_3 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_3_5 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_3_7 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_m_5_1 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_5_3 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_5_5 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_5_7 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_m_7_1 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_7_3 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_7_5 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_7_7 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); + + interference_abs_epi16(psi_r_p7_p7, ch_mag_int, a_r_p7_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_p5, ch_mag_int, a_r_p7_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_p3, ch_mag_int, a_r_p7_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_p1, ch_mag_int, a_r_p7_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_m1, ch_mag_int, a_r_p7_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_m3, ch_mag_int, a_r_p7_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_m5, ch_mag_int, a_r_p7_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p7_m7, ch_mag_int, a_r_p7_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_p7, ch_mag_int, a_r_p5_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_p5, ch_mag_int, a_r_p5_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_p3, ch_mag_int, a_r_p5_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_p1, ch_mag_int, a_r_p5_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_m1, ch_mag_int, a_r_p5_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_m3, ch_mag_int, a_r_p5_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_m5, ch_mag_int, a_r_p5_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p5_m7, ch_mag_int, a_r_p5_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_p7, ch_mag_int, a_r_p3_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_p5, ch_mag_int, a_r_p3_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_p3, ch_mag_int, a_r_p3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_p1, ch_mag_int, a_r_p3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_m1, ch_mag_int, a_r_p3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_m3, ch_mag_int, a_r_p3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_m5, ch_mag_int, a_r_p3_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p3_m7, ch_mag_int, a_r_p3_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_p7, ch_mag_int, a_r_p1_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_p5, ch_mag_int, a_r_p1_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_p3, ch_mag_int, a_r_p1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_p1, ch_mag_int, a_r_p1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_m1, ch_mag_int, a_r_p1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_m3, ch_mag_int, a_r_p1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_m5, ch_mag_int, a_r_p1_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_p1_m7, ch_mag_int, a_r_p1_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_p7, ch_mag_int, a_r_m1_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_p5, ch_mag_int, a_r_m1_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_p3, ch_mag_int, a_r_m1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_p1, ch_mag_int, a_r_m1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_m1, ch_mag_int, a_r_m1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_m3, ch_mag_int, a_r_m1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_m5, ch_mag_int, a_r_m1_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m1_m7, ch_mag_int, a_r_m1_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_p7, ch_mag_int, a_r_m3_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_p5, ch_mag_int, a_r_m3_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_p3, ch_mag_int, a_r_m3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_p1, ch_mag_int, a_r_m3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_m1, ch_mag_int, a_r_m3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_m3, ch_mag_int, a_r_m3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_m5, ch_mag_int, a_r_m3_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m3_m7, ch_mag_int, a_r_m3_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_p7, ch_mag_int, a_r_m5_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_p5, ch_mag_int, a_r_m5_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_p3, ch_mag_int, a_r_m5_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_p1, ch_mag_int, a_r_m5_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_m1, ch_mag_int, a_r_m5_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_m3, ch_mag_int, a_r_m5_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_m5, ch_mag_int, a_r_m5_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m5_m7, ch_mag_int, a_r_m5_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_p7, ch_mag_int, a_r_m7_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_p5, ch_mag_int, a_r_m7_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_p3, ch_mag_int, a_r_m7_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_p1, ch_mag_int, a_r_m7_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_m1, ch_mag_int, a_r_m7_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_m3, ch_mag_int, a_r_m7_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_m5, ch_mag_int, a_r_m7_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_r_m7_m7, ch_mag_int, a_r_m7_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + + interference_abs_epi16(psi_i_p7_p7, ch_mag_int, a_i_p7_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_p5, ch_mag_int, a_i_p7_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_p3, ch_mag_int, a_i_p7_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_p1, ch_mag_int, a_i_p7_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_m1, ch_mag_int, a_i_p7_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_m3, ch_mag_int, a_i_p7_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_m5, ch_mag_int, a_i_p7_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p7_m7, ch_mag_int, a_i_p7_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_p7, ch_mag_int, a_i_p5_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_p5, ch_mag_int, a_i_p5_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_p3, ch_mag_int, a_i_p5_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_p1, ch_mag_int, a_i_p5_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_m1, ch_mag_int, a_i_p5_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_m3, ch_mag_int, a_i_p5_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_m5, ch_mag_int, a_i_p5_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p5_m7, ch_mag_int, a_i_p5_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_p7, ch_mag_int, a_i_p3_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_p5, ch_mag_int, a_i_p3_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_p3, ch_mag_int, a_i_p3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_p1, ch_mag_int, a_i_p3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_m1, ch_mag_int, a_i_p3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_m3, ch_mag_int, a_i_p3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_m5, ch_mag_int, a_i_p3_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p3_m7, ch_mag_int, a_i_p3_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_p7, ch_mag_int, a_i_p1_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_p5, ch_mag_int, a_i_p1_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_p3, ch_mag_int, a_i_p1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_p1, ch_mag_int, a_i_p1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_m1, ch_mag_int, a_i_p1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_m3, ch_mag_int, a_i_p1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_m5, ch_mag_int, a_i_p1_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_p1_m7, ch_mag_int, a_i_p1_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_p7, ch_mag_int, a_i_m1_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_p5, ch_mag_int, a_i_m1_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_p3, ch_mag_int, a_i_m1_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_p1, ch_mag_int, a_i_m1_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_m1, ch_mag_int, a_i_m1_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_m3, ch_mag_int, a_i_m1_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_m5, ch_mag_int, a_i_m1_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m1_m7, ch_mag_int, a_i_m1_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_p7, ch_mag_int, a_i_m3_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_p5, ch_mag_int, a_i_m3_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_p3, ch_mag_int, a_i_m3_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_p1, ch_mag_int, a_i_m3_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_m1, ch_mag_int, a_i_m3_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_m3, ch_mag_int, a_i_m3_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_m5, ch_mag_int, a_i_m3_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m3_m7, ch_mag_int, a_i_m3_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_p7, ch_mag_int, a_i_m5_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_p5, ch_mag_int, a_i_m5_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_p3, ch_mag_int, a_i_m5_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_p1, ch_mag_int, a_i_m5_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_m1, ch_mag_int, a_i_m5_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_m3, ch_mag_int, a_i_m5_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_m5, ch_mag_int, a_i_m5_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m5_m7, ch_mag_int, a_i_m5_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_p7, ch_mag_int, a_i_m7_p7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_p5, ch_mag_int, a_i_m7_p5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_p3, ch_mag_int, a_i_m7_p3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_p1, ch_mag_int, a_i_m7_p1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_m1, ch_mag_int, a_i_m7_m1, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_m3, ch_mag_int, a_i_m7_m3, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_m5, ch_mag_int, a_i_m7_m5, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + interference_abs_epi16(psi_i_m7_m7, ch_mag_int, a_i_m7_m7, ONE_OVER_SQRT_10_Q15, THREE_OVER_SQRT_10); + + // Calculation of a group of two terms in the bit metric involving product of psi and interference + prodsum_psi_a_epi16(psi_r_p7_p7, a_r_p7_p7, psi_i_p7_p7, a_i_p7_p7, psi_a_p7_p7); + prodsum_psi_a_epi16(psi_r_p7_p5, a_r_p7_p5, psi_i_p7_p5, a_i_p7_p5, psi_a_p7_p5); + prodsum_psi_a_epi16(psi_r_p7_p3, a_r_p7_p3, psi_i_p7_p3, a_i_p7_p3, psi_a_p7_p3); + prodsum_psi_a_epi16(psi_r_p7_p1, a_r_p7_p1, psi_i_p7_p1, a_i_p7_p1, psi_a_p7_p1); + prodsum_psi_a_epi16(psi_r_p7_m1, a_r_p7_m1, psi_i_p7_m1, a_i_p7_m1, psi_a_p7_m1); + prodsum_psi_a_epi16(psi_r_p7_m3, a_r_p7_m3, psi_i_p7_m3, a_i_p7_m3, psi_a_p7_m3); + prodsum_psi_a_epi16(psi_r_p7_m5, a_r_p7_m5, psi_i_p7_m5, a_i_p7_m5, psi_a_p7_m5); + prodsum_psi_a_epi16(psi_r_p7_m7, a_r_p7_m7, psi_i_p7_m7, a_i_p7_m7, psi_a_p7_m7); + prodsum_psi_a_epi16(psi_r_p5_p7, a_r_p5_p7, psi_i_p5_p7, a_i_p5_p7, psi_a_p5_p7); + prodsum_psi_a_epi16(psi_r_p5_p5, a_r_p5_p5, psi_i_p5_p5, a_i_p5_p5, psi_a_p5_p5); + prodsum_psi_a_epi16(psi_r_p5_p3, a_r_p5_p3, psi_i_p5_p3, a_i_p5_p3, psi_a_p5_p3); + prodsum_psi_a_epi16(psi_r_p5_p1, a_r_p5_p1, psi_i_p5_p1, a_i_p5_p1, psi_a_p5_p1); + prodsum_psi_a_epi16(psi_r_p5_m1, a_r_p5_m1, psi_i_p5_m1, a_i_p5_m1, psi_a_p5_m1); + prodsum_psi_a_epi16(psi_r_p5_m3, a_r_p5_m3, psi_i_p5_m3, a_i_p5_m3, psi_a_p5_m3); + prodsum_psi_a_epi16(psi_r_p5_m5, a_r_p5_m5, psi_i_p5_m5, a_i_p5_m5, psi_a_p5_m5); + prodsum_psi_a_epi16(psi_r_p5_m7, a_r_p5_m7, psi_i_p5_m7, a_i_p5_m7, psi_a_p5_m7); + prodsum_psi_a_epi16(psi_r_p3_p7, a_r_p3_p7, psi_i_p3_p7, a_i_p3_p7, psi_a_p3_p7); + prodsum_psi_a_epi16(psi_r_p3_p5, a_r_p3_p5, psi_i_p3_p5, a_i_p3_p5, psi_a_p3_p5); + prodsum_psi_a_epi16(psi_r_p3_p3, a_r_p3_p3, psi_i_p3_p3, a_i_p3_p3, psi_a_p3_p3); + prodsum_psi_a_epi16(psi_r_p3_p1, a_r_p3_p1, psi_i_p3_p1, a_i_p3_p1, psi_a_p3_p1); + prodsum_psi_a_epi16(psi_r_p3_m1, a_r_p3_m1, psi_i_p3_m1, a_i_p3_m1, psi_a_p3_m1); + prodsum_psi_a_epi16(psi_r_p3_m3, a_r_p3_m3, psi_i_p3_m3, a_i_p3_m3, psi_a_p3_m3); + prodsum_psi_a_epi16(psi_r_p3_m5, a_r_p3_m5, psi_i_p3_m5, a_i_p3_m5, psi_a_p3_m5); + prodsum_psi_a_epi16(psi_r_p3_m7, a_r_p3_m7, psi_i_p3_m7, a_i_p3_m7, psi_a_p3_m7); + prodsum_psi_a_epi16(psi_r_p1_p7, a_r_p1_p7, psi_i_p1_p7, a_i_p1_p7, psi_a_p1_p7); + prodsum_psi_a_epi16(psi_r_p1_p5, a_r_p1_p5, psi_i_p1_p5, a_i_p1_p5, psi_a_p1_p5); + prodsum_psi_a_epi16(psi_r_p1_p3, a_r_p1_p3, psi_i_p1_p3, a_i_p1_p3, psi_a_p1_p3); + prodsum_psi_a_epi16(psi_r_p1_p1, a_r_p1_p1, psi_i_p1_p1, a_i_p1_p1, psi_a_p1_p1); + prodsum_psi_a_epi16(psi_r_p1_m1, a_r_p1_m1, psi_i_p1_m1, a_i_p1_m1, psi_a_p1_m1); + prodsum_psi_a_epi16(psi_r_p1_m3, a_r_p1_m3, psi_i_p1_m3, a_i_p1_m3, psi_a_p1_m3); + prodsum_psi_a_epi16(psi_r_p1_m5, a_r_p1_m5, psi_i_p1_m5, a_i_p1_m5, psi_a_p1_m5); + prodsum_psi_a_epi16(psi_r_p1_m7, a_r_p1_m7, psi_i_p1_m7, a_i_p1_m7, psi_a_p1_m7); + prodsum_psi_a_epi16(psi_r_m1_p7, a_r_m1_p7, psi_i_m1_p7, a_i_m1_p7, psi_a_m1_p7); + prodsum_psi_a_epi16(psi_r_m1_p5, a_r_m1_p5, psi_i_m1_p5, a_i_m1_p5, psi_a_m1_p5); + prodsum_psi_a_epi16(psi_r_m1_p3, a_r_m1_p3, psi_i_m1_p3, a_i_m1_p3, psi_a_m1_p3); + prodsum_psi_a_epi16(psi_r_m1_p1, a_r_m1_p1, psi_i_m1_p1, a_i_m1_p1, psi_a_m1_p1); + prodsum_psi_a_epi16(psi_r_m1_m1, a_r_m1_m1, psi_i_m1_m1, a_i_m1_m1, psi_a_m1_m1); + prodsum_psi_a_epi16(psi_r_m1_m3, a_r_m1_m3, psi_i_m1_m3, a_i_m1_m3, psi_a_m1_m3); + prodsum_psi_a_epi16(psi_r_m1_m5, a_r_m1_m5, psi_i_m1_m5, a_i_m1_m5, psi_a_m1_m5); + prodsum_psi_a_epi16(psi_r_m1_m7, a_r_m1_m7, psi_i_m1_m7, a_i_m1_m7, psi_a_m1_m7); + prodsum_psi_a_epi16(psi_r_m3_p7, a_r_m3_p7, psi_i_m3_p7, a_i_m3_p7, psi_a_m3_p7); + prodsum_psi_a_epi16(psi_r_m3_p5, a_r_m3_p5, psi_i_m3_p5, a_i_m3_p5, psi_a_m3_p5); + prodsum_psi_a_epi16(psi_r_m3_p3, a_r_m3_p3, psi_i_m3_p3, a_i_m3_p3, psi_a_m3_p3); + prodsum_psi_a_epi16(psi_r_m3_p1, a_r_m3_p1, psi_i_m3_p1, a_i_m3_p1, psi_a_m3_p1); + prodsum_psi_a_epi16(psi_r_m3_m1, a_r_m3_m1, psi_i_m3_m1, a_i_m3_m1, psi_a_m3_m1); + prodsum_psi_a_epi16(psi_r_m3_m3, a_r_m3_m3, psi_i_m3_m3, a_i_m3_m3, psi_a_m3_m3); + prodsum_psi_a_epi16(psi_r_m3_m5, a_r_m3_m5, psi_i_m3_m5, a_i_m3_m5, psi_a_m3_m5); + prodsum_psi_a_epi16(psi_r_m3_m7, a_r_m3_m7, psi_i_m3_m7, a_i_m3_m7, psi_a_m3_m7); + prodsum_psi_a_epi16(psi_r_m5_p7, a_r_m5_p7, psi_i_m5_p7, a_i_m5_p7, psi_a_m5_p7); + prodsum_psi_a_epi16(psi_r_m5_p5, a_r_m5_p5, psi_i_m5_p5, a_i_m5_p5, psi_a_m5_p5); + prodsum_psi_a_epi16(psi_r_m5_p3, a_r_m5_p3, psi_i_m5_p3, a_i_m5_p3, psi_a_m5_p3); + prodsum_psi_a_epi16(psi_r_m5_p1, a_r_m5_p1, psi_i_m5_p1, a_i_m5_p1, psi_a_m5_p1); + prodsum_psi_a_epi16(psi_r_m5_m1, a_r_m5_m1, psi_i_m5_m1, a_i_m5_m1, psi_a_m5_m1); + prodsum_psi_a_epi16(psi_r_m5_m3, a_r_m5_m3, psi_i_m5_m3, a_i_m5_m3, psi_a_m5_m3); + prodsum_psi_a_epi16(psi_r_m5_m5, a_r_m5_m5, psi_i_m5_m5, a_i_m5_m5, psi_a_m5_m5); + prodsum_psi_a_epi16(psi_r_m5_m7, a_r_m5_m7, psi_i_m5_m7, a_i_m5_m7, psi_a_m5_m7); + prodsum_psi_a_epi16(psi_r_m7_p7, a_r_m7_p7, psi_i_m7_p7, a_i_m7_p7, psi_a_m7_p7); + prodsum_psi_a_epi16(psi_r_m7_p5, a_r_m7_p5, psi_i_m7_p5, a_i_m7_p5, psi_a_m7_p5); + prodsum_psi_a_epi16(psi_r_m7_p3, a_r_m7_p3, psi_i_m7_p3, a_i_m7_p3, psi_a_m7_p3); + prodsum_psi_a_epi16(psi_r_m7_p1, a_r_m7_p1, psi_i_m7_p1, a_i_m7_p1, psi_a_m7_p1); + prodsum_psi_a_epi16(psi_r_m7_m1, a_r_m7_m1, psi_i_m7_m1, a_i_m7_m1, psi_a_m7_m1); + prodsum_psi_a_epi16(psi_r_m7_m3, a_r_m7_m3, psi_i_m7_m3, a_i_m7_m3, psi_a_m7_m3); + prodsum_psi_a_epi16(psi_r_m7_m5, a_r_m7_m5, psi_i_m7_m5, a_i_m7_m5, psi_a_m7_m5); + prodsum_psi_a_epi16(psi_r_m7_m7, a_r_m7_m7, psi_i_m7_m7, a_i_m7_m7, psi_a_m7_m7); + + // Calculation of a group of two terms in the bit metric involving squares of interference + square_a_epi16(a_r_p7_p7, a_i_p7_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_p7); + square_a_epi16(a_r_p7_p5, a_i_p7_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_p5); + square_a_epi16(a_r_p7_p3, a_i_p7_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_p3); + square_a_epi16(a_r_p7_p1, a_i_p7_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_p1); + square_a_epi16(a_r_p7_m1, a_i_p7_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_m1); + square_a_epi16(a_r_p7_m3, a_i_p7_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_m3); + square_a_epi16(a_r_p7_m5, a_i_p7_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_m5); + square_a_epi16(a_r_p7_m7, a_i_p7_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p7_m7); + square_a_epi16(a_r_p5_p7, a_i_p5_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_p7); + square_a_epi16(a_r_p5_p5, a_i_p5_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_p5); + square_a_epi16(a_r_p5_p3, a_i_p5_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_p3); + square_a_epi16(a_r_p5_p1, a_i_p5_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_p1); + square_a_epi16(a_r_p5_m1, a_i_p5_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_m1); + square_a_epi16(a_r_p5_m3, a_i_p5_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_m3); + square_a_epi16(a_r_p5_m5, a_i_p5_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_m5); + square_a_epi16(a_r_p5_m7, a_i_p5_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p5_m7); + square_a_epi16(a_r_p3_p7, a_i_p3_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_p7); + square_a_epi16(a_r_p3_p5, a_i_p3_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_p5); + square_a_epi16(a_r_p3_p3, a_i_p3_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_p3); + square_a_epi16(a_r_p3_p1, a_i_p3_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_p1); + square_a_epi16(a_r_p3_m1, a_i_p3_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_m1); + square_a_epi16(a_r_p3_m3, a_i_p3_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_m3); + square_a_epi16(a_r_p3_m5, a_i_p3_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_m5); + square_a_epi16(a_r_p3_m7, a_i_p3_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p3_m7); + square_a_epi16(a_r_p1_p7, a_i_p1_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_p7); + square_a_epi16(a_r_p1_p5, a_i_p1_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_p5); + square_a_epi16(a_r_p1_p3, a_i_p1_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_p3); + square_a_epi16(a_r_p1_p1, a_i_p1_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_p1); + square_a_epi16(a_r_p1_m1, a_i_p1_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_m1); + square_a_epi16(a_r_p1_m3, a_i_p1_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_m3); + square_a_epi16(a_r_p1_m5, a_i_p1_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_m5); + square_a_epi16(a_r_p1_m7, a_i_p1_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_p1_m7); + square_a_epi16(a_r_m1_p7, a_i_m1_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_p7); + square_a_epi16(a_r_m1_p5, a_i_m1_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_p5); + square_a_epi16(a_r_m1_p3, a_i_m1_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_p3); + square_a_epi16(a_r_m1_p1, a_i_m1_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_p1); + square_a_epi16(a_r_m1_m1, a_i_m1_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_m1); + square_a_epi16(a_r_m1_m3, a_i_m1_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_m3); + square_a_epi16(a_r_m1_m5, a_i_m1_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_m5); + square_a_epi16(a_r_m1_m7, a_i_m1_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m1_m7); + square_a_epi16(a_r_m3_p7, a_i_m3_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_p7); + square_a_epi16(a_r_m3_p5, a_i_m3_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_p5); + square_a_epi16(a_r_m3_p3, a_i_m3_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_p3); + square_a_epi16(a_r_m3_p1, a_i_m3_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_p1); + square_a_epi16(a_r_m3_m1, a_i_m3_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_m1); + square_a_epi16(a_r_m3_m3, a_i_m3_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_m3); + square_a_epi16(a_r_m3_m5, a_i_m3_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_m5); + square_a_epi16(a_r_m3_m7, a_i_m3_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m3_m7); + square_a_epi16(a_r_m5_p7, a_i_m5_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_p7); + square_a_epi16(a_r_m5_p5, a_i_m5_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_p5); + square_a_epi16(a_r_m5_p3, a_i_m5_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_p3); + square_a_epi16(a_r_m5_p1, a_i_m5_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_p1); + square_a_epi16(a_r_m5_m1, a_i_m5_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_m1); + square_a_epi16(a_r_m5_m3, a_i_m5_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_m3); + square_a_epi16(a_r_m5_m5, a_i_m5_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_m5); + square_a_epi16(a_r_m5_m7, a_i_m5_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m5_m7); + square_a_epi16(a_r_m7_p7, a_i_m7_p7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_p7); + square_a_epi16(a_r_m7_p5, a_i_m7_p5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_p5); + square_a_epi16(a_r_m7_p3, a_i_m7_p3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_p3); + square_a_epi16(a_r_m7_p1, a_i_m7_p1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_p1); + square_a_epi16(a_r_m7_m1, a_i_m7_m1, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_m1); + square_a_epi16(a_r_m7_m3, a_i_m7_m3, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_m3); + square_a_epi16(a_r_m7_m5, a_i_m7_m5, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_m5); + square_a_epi16(a_r_m7_m7, a_i_m7_m7, ch_mag_int, SQRT_10_OVER_FOUR, a_sq_m7_m7); + + // Computing different multiples of ||h0||^2 + // x=1, y=1 + ch_mag_2_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,ONE_OVER_FOUR_SQRT_42); + ch_mag_2_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_2_over_42_with_sigma2,1); + // x=1, y=3 + ch_mag_10_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,FIVE_OVER_FOUR_SQRT_42); + ch_mag_10_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_10_over_42_with_sigma2,1); + // x=1, x=5 + ch_mag_26_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,THIRTEEN_OVER_FOUR_SQRT_42); + ch_mag_26_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_26_over_42_with_sigma2,1); + // x=1, y=7 + ch_mag_50_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,TWENTYFIVE_OVER_FOUR_SQRT_42); + ch_mag_50_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_50_over_42_with_sigma2,1); + // x=3, y=3 + ch_mag_18_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,NINE_OVER_FOUR_SQRT_42); + ch_mag_18_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_18_over_42_with_sigma2,1); + // x=3, y=5 + ch_mag_34_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,SEVENTEEN_OVER_FOUR_SQRT_42); + ch_mag_34_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_34_over_42_with_sigma2,1); + // x=3, y=7 + ch_mag_58_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,TWENTYNINE_OVER_FOUR_SQRT_42); + ch_mag_58_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_58_over_42_with_sigma2,2); + // x=5, y=5 + ch_mag_50_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,TWENTYFIVE_OVER_FOUR_SQRT_42); + ch_mag_50_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_50_over_42_with_sigma2,1); + // x=5, y=7 + ch_mag_74_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,THIRTYSEVEN_OVER_FOUR_SQRT_42); + ch_mag_74_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_74_over_42_with_sigma2,2); + // x=7, y=7 + ch_mag_98_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,FORTYNINE_OVER_FOUR_SQRT_42); + ch_mag_98_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_98_over_42_with_sigma2,2); + + // Computing Metrics + xmm0 = _mm256_subs_epi16(psi_a_p7_p7, a_sq_p7_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_7); + bit_met_p7_p7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_p5, a_sq_p7_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_5); + bit_met_p7_p5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_p3, a_sq_p7_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_3); + bit_met_p7_p3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_p1, a_sq_p7_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_1); + bit_met_p7_p1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m1, a_sq_p7_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_1); + bit_met_p7_m1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m3, a_sq_p7_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_3); + bit_met_p7_m3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m5, a_sq_p7_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_5); + bit_met_p7_m5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m7, a_sq_p7_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_7); + bit_met_p7_m7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p7, a_sq_p5_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_7); + bit_met_p5_p7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p5, a_sq_p5_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_5); + bit_met_p5_p5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p3, a_sq_p5_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_3); + bit_met_p5_p3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p1, a_sq_p5_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_1); + bit_met_p5_p1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m1, a_sq_p5_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_1); + bit_met_p5_m1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m3, a_sq_p5_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_3); + bit_met_p5_m3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m5, a_sq_p5_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_5); + bit_met_p5_m5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m7, a_sq_p5_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_7); + bit_met_p5_m7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p7, a_sq_p3_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_7); + bit_met_p3_p7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p5, a_sq_p3_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_5); + bit_met_p3_p5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p3, a_sq_p3_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_3); + bit_met_p3_p3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p1, a_sq_p3_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_1); + bit_met_p3_p1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m1, a_sq_p3_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_1); + bit_met_p3_m1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m3, a_sq_p3_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_3); + bit_met_p3_m3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m5, a_sq_p3_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_5); + bit_met_p3_m5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m7, a_sq_p3_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_7); + bit_met_p3_m7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p7, a_sq_p1_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_7); + bit_met_p1_p7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p5, a_sq_p1_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_5); + bit_met_p1_p5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p3, a_sq_p1_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_3); + bit_met_p1_p3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p1, a_sq_p1_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_1); + bit_met_p1_p1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m1, a_sq_p1_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_1); + bit_met_p1_m1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m3, a_sq_p1_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_3); + bit_met_p1_m3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m5, a_sq_p1_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_5); + bit_met_p1_m5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m7, a_sq_p1_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_7); + bit_met_p1_m7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + + xmm0 = _mm256_subs_epi16(psi_a_m1_p7, a_sq_m1_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_7); + bit_met_m1_p7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_p5, a_sq_m1_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_5); + bit_met_m1_p5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_p3, a_sq_m1_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_3); + bit_met_m1_p3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_p1, a_sq_m1_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_1); + bit_met_m1_p1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m1, a_sq_m1_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_1); + bit_met_m1_m1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m3, a_sq_m1_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_3); + bit_met_m1_m3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m5, a_sq_m1_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_5); + bit_met_m1_m5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m7, a_sq_m1_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_7); + bit_met_m1_m7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p7, a_sq_m3_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_7); + bit_met_m3_p7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p5, a_sq_m3_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_5); + bit_met_m3_p5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p3, a_sq_m3_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_3); + bit_met_m3_p3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p1, a_sq_m3_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_1); + bit_met_m3_p1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m1, a_sq_m3_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_1); + bit_met_m3_m1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m3, a_sq_m3_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_3); + bit_met_m3_m3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m5, a_sq_m3_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_5); + bit_met_m3_m5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m7, a_sq_m3_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_7); + bit_met_m3_m7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p7, a_sq_m5_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_7); + bit_met_m5_p7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p5, a_sq_m5_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_5); + bit_met_m5_p5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p3, a_sq_m5_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_3); + bit_met_m5_p3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p1, a_sq_m5_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_1); + bit_met_m5_p1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m1, a_sq_m5_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_1); + bit_met_m5_m1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m3, a_sq_m5_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_3); + bit_met_m5_m3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m5, a_sq_m5_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_5); + bit_met_m5_m5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m7, a_sq_m5_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_7); + bit_met_m5_m7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p7, a_sq_m7_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_7); + bit_met_m7_p7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p5, a_sq_m7_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_5); + bit_met_m7_p5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p3, a_sq_m7_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_3); + bit_met_m7_p3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p1, a_sq_m7_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_1); + bit_met_m7_p1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m1, a_sq_m7_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_1); + bit_met_m7_m1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m3, a_sq_m7_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_3); + bit_met_m7_m3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m5, a_sq_m7_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_5); + bit_met_m7_m5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m7, a_sq_m7_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_7); + bit_met_m7_m7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + + // Detection for 1st bit (LTE mapping) + // bit = 1 + xmm0 = _mm256_max_epi16(bit_met_m7_p7, bit_met_m7_p5); + xmm1 = _mm256_max_epi16(bit_met_m7_p3, bit_met_m7_p1); + xmm2 = _mm256_max_epi16(bit_met_m7_m1, bit_met_m7_m3); + xmm3 = _mm256_max_epi16(bit_met_m7_m5, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m5_p5); + xmm1 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m5_p1); + xmm2 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m5_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m5_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m3_p7, bit_met_m3_p5); + xmm1 = _mm256_max_epi16(bit_met_m3_p3, bit_met_m3_p1); + xmm2 = _mm256_max_epi16(bit_met_m3_m1, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m3_m5, bit_met_m3_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m1_p5); + xmm1 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m1_m3); + xmm3 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m1_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + // bit = 0 + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p7_p5); + xmm1 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p7_p1); + xmm2 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p7_m3); + xmm3 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p5_p7, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p5_p3, bit_met_p5_p1); + xmm2 = _mm256_max_epi16(bit_met_p5_m1, bit_met_p5_m3); + xmm3 = _mm256_max_epi16(bit_met_p5_m5, bit_met_p5_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p3_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p3_p1); + xmm2 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p3_m3); + xmm3 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p3_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p1_p7, bit_met_p1_p5); + xmm1 = _mm256_max_epi16(bit_met_p1_p3, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_p1_m1, bit_met_p1_m3); + xmm3 = _mm256_max_epi16(bit_met_p1_m5, bit_met_p1_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y0r = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 2nd bit (LTE mapping) + // bit = 1 + xmm0 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + // bit = 0 + xmm0 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m7_p1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m7_p5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y1r = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 3rd bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_m7_m7, bit_met_m7_m5); + xmm1 = _mm256_max_epi16(bit_met_m7_m3, bit_met_m7_m1); + xmm2 = _mm256_max_epi16(bit_met_m7_p1, bit_met_m7_p3); + xmm3 = _mm256_max_epi16(bit_met_m7_p5, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m5_m5); + xmm1 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m5_m1); + xmm2 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p5_m7, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p5_m3, bit_met_p5_m1); + xmm2 = _mm256_max_epi16(bit_met_p5_p1, bit_met_p5_p3); + xmm3 = _mm256_max_epi16(bit_met_p5_p5, bit_met_p5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p7_m5); + xmm1 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p7_m1); + xmm2 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p7_p3); + xmm3 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_m3_m7, bit_met_m3_m5); + xmm1 = _mm256_max_epi16(bit_met_m3_m3, bit_met_m3_m1); + xmm2 = _mm256_max_epi16(bit_met_m3_p1, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m3_p5, bit_met_m3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m1_m5); + xmm1 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m1_p3); + xmm3 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p1_m7, bit_met_p1_m5); + xmm1 = _mm256_max_epi16(bit_met_p1_m3, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_p1_p1, bit_met_p1_p3); + xmm3 = _mm256_max_epi16(bit_met_p1_p5, bit_met_p1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p3_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p3_m1); + xmm2 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p3_p3); + xmm3 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y2r = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 4th bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m7_p1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y0i = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + + // Detection for 5th bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_m7_m7, bit_met_m7_m5); + xmm1 = _mm256_max_epi16(bit_met_m7_m3, bit_met_m7_m1); + xmm2 = _mm256_max_epi16(bit_met_m7_p1, bit_met_m7_p3); + xmm3 = _mm256_max_epi16(bit_met_m7_p5, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m1_m5); + xmm1 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m1_p3); + xmm3 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p1_m7, bit_met_p1_m5); + xmm1 = _mm256_max_epi16(bit_met_p1_m3, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_p1_p1, bit_met_p1_p3); + xmm3 = _mm256_max_epi16(bit_met_p1_p5, bit_met_p1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p7_m5); + xmm1 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p7_m1); + xmm2 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p7_p3); + xmm3 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m5_m5); + xmm1 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m5_m1); + xmm2 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m3_m7, bit_met_m3_m5); + xmm1 = _mm256_max_epi16(bit_met_m3_m3, bit_met_m3_m1); + xmm2 = _mm256_max_epi16(bit_met_m3_p1, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m3_p5, bit_met_m3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p3_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p3_m1); + xmm2 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p3_p3); + xmm3 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p5_m7, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p5_m3, bit_met_p5_m1); + xmm2 = _mm256_max_epi16(bit_met_p5_p1, bit_met_p5_p3); + xmm3 = _mm256_max_epi16(bit_met_p5_p5, bit_met_p5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y1i = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 6th bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m7_p5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y2i = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // map to output stream, difficult to do in SIMD since we have 6 16bit LLRs + // RE 1 + j = 48*i; + stream0_out[j + 0] = ((short *)&y0r)[0]; + stream0_out[j + 1] = ((short *)&y1r)[0]; + stream0_out[j + 2] = ((short *)&y2r)[0]; + stream0_out[j + 3] = ((short *)&y0i)[0]; + stream0_out[j + 4] = ((short *)&y1i)[0]; + stream0_out[j + 5] = ((short *)&y2i)[0]; + // RE 2 + stream0_out[j + 6] = ((short *)&y0r)[1]; + stream0_out[j + 7] = ((short *)&y1r)[1]; + stream0_out[j + 8] = ((short *)&y2r)[1]; + stream0_out[j + 9] = ((short *)&y0i)[1]; + stream0_out[j + 10] = ((short *)&y1i)[1]; + stream0_out[j + 11] = ((short *)&y2i)[1]; + // RE 3 + stream0_out[j + 12] = ((short *)&y0r)[2]; + stream0_out[j + 13] = ((short *)&y1r)[2]; + stream0_out[j + 14] = ((short *)&y2r)[2]; + stream0_out[j + 15] = ((short *)&y0i)[2]; + stream0_out[j + 16] = ((short *)&y1i)[2]; + stream0_out[j + 17] = ((short *)&y2i)[2]; + // RE 4 + stream0_out[j + 18] = ((short *)&y0r)[3]; + stream0_out[j + 19] = ((short *)&y1r)[3]; + stream0_out[j + 20] = ((short *)&y2r)[3]; + stream0_out[j + 21] = ((short *)&y0i)[3]; + stream0_out[j + 22] = ((short *)&y1i)[3]; + stream0_out[j + 23] = ((short *)&y2i)[3]; + // RE 5 + stream0_out[j + 24] = ((short *)&y0r)[4]; + stream0_out[j + 25] = ((short *)&y1r)[4]; + stream0_out[j + 26] = ((short *)&y2r)[4]; + stream0_out[j + 27] = ((short *)&y0i)[4]; + stream0_out[j + 28] = ((short *)&y1i)[4]; + stream0_out[j + 29] = ((short *)&y2i)[4]; + // RE 6 + stream0_out[j + 30] = ((short *)&y0r)[5]; + stream0_out[j + 31] = ((short *)&y1r)[5]; + stream0_out[j + 32] = ((short *)&y2r)[5]; + stream0_out[j + 33] = ((short *)&y0i)[5]; + stream0_out[j + 34] = ((short *)&y1i)[5]; + stream0_out[j + 35] = ((short *)&y2i)[5]; + // RE 7 + stream0_out[j + 36] = ((short *)&y0r)[6]; + stream0_out[j + 37] = ((short *)&y1r)[6]; + stream0_out[j + 38] = ((short *)&y2r)[6]; + stream0_out[j + 39] = ((short *)&y0i)[6]; + stream0_out[j + 40] = ((short *)&y1i)[6]; + stream0_out[j + 41] = ((short *)&y2i)[6]; + // RE 8 + stream0_out[j + 42] = ((short *)&y0r)[7]; + stream0_out[j + 43] = ((short *)&y1r)[7]; + stream0_out[j + 44] = ((short *)&y2r)[7]; + stream0_out[j + 45] = ((short *)&y0i)[7]; + stream0_out[j + 46] = ((short *)&y1i)[7]; + stream0_out[j + 47] = ((short *)&y2i)[7]; + + // RE 9 + stream0_out[j + 48] = ((short *)&y0r)[8]; + stream0_out[j + 49] = ((short *)&y1r)[8]; + stream0_out[j + 50] = ((short *)&y2r)[8]; + stream0_out[j + 51] = ((short *)&y0i)[8]; + stream0_out[j + 52] = ((short *)&y1i)[8]; + stream0_out[j + 53] = ((short *)&y2i)[8]; + // RE 10 + stream0_out[j + 54] = ((short *)&y0r)[9]; + stream0_out[j + 55] = ((short *)&y1r)[9]; + stream0_out[j + 56] = ((short *)&y2r)[9]; + stream0_out[j + 57] = ((short *)&y0i)[9]; + stream0_out[j + 58] = ((short *)&y1i)[9]; + stream0_out[j + 59] = ((short *)&y2i)[9]; + // RE 11 + stream0_out[j + 60] = ((short *)&y0r)[10]; + stream0_out[j + 61] = ((short *)&y1r)[10]; + stream0_out[j + 62] = ((short *)&y2r)[10]; + stream0_out[j + 63] = ((short *)&y0i)[10]; + stream0_out[j + 64] = ((short *)&y1i)[10]; + stream0_out[j + 65] = ((short *)&y2i)[10]; + // RE 12 + stream0_out[j + 66] = ((short *)&y0r)[11]; + stream0_out[j + 67] = ((short *)&y1r)[11]; + stream0_out[j + 68] = ((short *)&y2r)[11]; + stream0_out[j + 69] = ((short *)&y0i)[11]; + stream0_out[j + 70] = ((short *)&y1i)[11]; + stream0_out[j + 71] = ((short *)&y2i)[11]; + // RE 13 + stream0_out[j + 72] = ((short *)&y0r)[12]; + stream0_out[j + 73] = ((short *)&y1r)[12]; + stream0_out[j + 74] = ((short *)&y2r)[12]; + stream0_out[j + 75] = ((short *)&y0i)[12]; + stream0_out[j + 76] = ((short *)&y1i)[12]; + stream0_out[j + 77] = ((short *)&y2i)[12]; + // RE 14 + stream0_out[j + 78] = ((short *)&y0r)[13]; + stream0_out[j + 79] = ((short *)&y1r)[13]; + stream0_out[j + 80] = ((short *)&y2r)[13]; + stream0_out[j + 81] = ((short *)&y0i)[13]; + stream0_out[j + 82] = ((short *)&y1i)[13]; + stream0_out[j + 83] = ((short *)&y2i)[13]; + // RE 15 + stream0_out[j + 84] = ((short *)&y0r)[14]; + stream0_out[j + 85] = ((short *)&y1r)[14]; + stream0_out[j + 86] = ((short *)&y2r)[14]; + stream0_out[j + 87] = ((short *)&y0i)[14]; + stream0_out[j + 88] = ((short *)&y1i)[14]; + stream0_out[j + 89] = ((short *)&y2i)[14]; + // RE 16 + stream0_out[j + 90] = ((short *)&y0r)[15]; + stream0_out[j + 91] = ((short *)&y1r)[15]; + stream0_out[j + 92] = ((short *)&y2r)[15]; + stream0_out[j + 93] = ((short *)&y0i)[15]; + stream0_out[j + 94] = ((short *)&y1i)[15]; + stream0_out[j + 95] = ((short *)&y2i)[15]; + +#elif defined(__arm__) + +#endif + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif + +} + +void qam64_qam64_avx2(int32_t *stream0_in, + int32_t *stream1_in, + int32_t *ch_mag, + int32_t *ch_mag_i, + int16_t *stream0_out, + int32_t *rho01, + int length + ) +{ + + /* + Author: S. Wagner + Date: 28-02-17 + + Input: + stream0_in: MF filter for 1st stream, i.e., y0=h0'*y + stream1_in: MF filter for 2nd stream, i.e., y1=h1'*y + ch_mag: 4*h0/sqrt(42), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + ch_mag_i: 4*h1/sqrt(42), [Re0 Im0 Re1 Im1] s.t. Im0=Re0, Im1=Re1, etc + rho01: Channel cross correlation, i.e., h1'*h0 + + Output: + stream0_out: output LLRs for 1st stream + */ + +#if defined(__x86_64__) || defined(__i386__) + + __m256i *rho01_256i = (__m256i *)rho01; + __m256i *stream0_256i_in = (__m256i *)stream0_in; + __m256i *stream1_256i_in = (__m256i *)stream1_in; + __m256i *ch_mag_256i = (__m256i *)ch_mag; + __m256i *ch_mag_256i_i = (__m256i *)ch_mag_i; + + __m256i ONE_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(10112)); // round(1/sqrt(42)*2^16) + __m256i THREE_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(30337)); // round(3/sqrt(42)*2^16) + __m256i FIVE_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(25281)); // round(5/sqrt(42)*2^15) + __m256i SEVEN_OVER_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(17697)); // round(7/sqrt(42)*2^14) Q2.14 + __m256i ONE_OVER_SQRT_2 = _mm256_broadcastw_epi16(_mm_set1_epi16(23170)); // round(1/sqrt(2)*2^15) + __m256i ONE_OVER_SQRT_2_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(3575)); // round(1/sqrt(2*42)*2^15) + __m256i THREE_OVER_SQRT_2_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(10726)); // round(3/sqrt(2*42)*2^15) + __m256i FIVE_OVER_SQRT_2_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(17876)); // round(5/sqrt(2*42)*2^15) + __m256i SEVEN_OVER_SQRT_2_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(25027)); // round(7/sqrt(2*42)*2^15) + __m256i FORTYNINE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(30969)); // round(49/(4*sqrt(42))*2^14), Q2.14 + __m256i THIRTYSEVEN_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(23385)); // round(37/(4*sqrt(42))*2^14), Q2.14 + __m256i TWENTYFIVE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(31601)); // round(25/(4*sqrt(42))*2^15) + __m256i TWENTYNINE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(18329)); // round(29/(4*sqrt(42))*2^15), Q2.14 + __m256i SEVENTEEN_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(21489)); // round(17/(4*sqrt(42))*2^15) + __m256i NINE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(11376)); // round(9/(4*sqrt(42))*2^15) + __m256i THIRTEEN_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(16433)); // round(13/(4*sqrt(42))*2^15) + __m256i FIVE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(6320)); // round(5/(4*sqrt(42))*2^15) + __m256i ONE_OVER_FOUR_SQRT_42 = _mm256_broadcastw_epi16(_mm_set1_epi16(1264)); // round(1/(4*sqrt(42))*2^15) + __m256i SQRT_42_OVER_FOUR = _mm256_broadcastw_epi16(_mm_set1_epi16(13272)); // round(sqrt(42)/4*2^13), Q3.12 + + __m256i ch_mag_des; + __m256i ch_mag_int; + __m256i ch_mag_98_over_42_with_sigma2; + __m256i ch_mag_74_over_42_with_sigma2; + __m256i ch_mag_58_over_42_with_sigma2; + __m256i ch_mag_50_over_42_with_sigma2; + __m256i ch_mag_34_over_42_with_sigma2; + __m256i ch_mag_18_over_42_with_sigma2; + __m256i ch_mag_26_over_42_with_sigma2; + __m256i ch_mag_10_over_42_with_sigma2; + __m256i ch_mag_2_over_42_with_sigma2; + __m256i y0r_one_over_sqrt_21; + __m256i y0r_three_over_sqrt_21; + __m256i y0r_five_over_sqrt_21; + __m256i y0r_seven_over_sqrt_21; + __m256i y0i_one_over_sqrt_21; + __m256i y0i_three_over_sqrt_21; + __m256i y0i_five_over_sqrt_21; + __m256i y0i_seven_over_sqrt_21; + __m256i ch_mag_int_with_sigma2; + __m256i two_ch_mag_int_with_sigma2; + __m256i three_ch_mag_int_with_sigma2; +#elif defined(__arm__) + +#endif + + int i,j; + uint32_t len256 = (length)>>3; + + for (i=0; i<len256; i+=2) { + +#if defined(__x86_64__) || defined(__i386__) + + // Get rho + /* + xmm0 = rho01_256i[i]; + xmm1 = rho01_256i[i+1]; + xmm0 = _mm256_shufflelo_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shufflehi_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shuffle_epi32(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + + xmm1 = _mm256_shufflelo_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shufflehi_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shuffle_epi32(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + + //xmm0 = [Re(0,1,2,3) Im(0,1,2,3) Re(4,5,6,7) Im(4,5,6,7)] + //xmm0 = [Re(8,9,10,11) Im(8,9,10,11) Re(12,13,14,15) Im(12,13,14,15)] + + xmm2 = _mm256_unpacklo_epi64(xmm0, xmm1); + //xmm2 = [Re(0,1,2,3) Re(8,9,10,11) Re(4,5,6,7) Re(12,13,14,15)] + xmm2 = _mm256_permute4x64_epi64(xmm2,0xd8); // Re(rho) + + xmm3 = _mm256_unpackhi_epi64(xmm0, xmm1); + //xmm3 = [Im(0,1,2,3) Im(8,9,10,11) Im(4,5,6,7) Im(12,13,14,15)] + xmm3 = _mm256_permute4x64_epi64(xmm3,0xd8); // Im(rho) + */ + + seperate_real_imag_parts(&xmm2, &xmm3, rho01_256i[i], rho01_256i[i+1]); + + rho_rpi = _mm256_adds_epi16(xmm2,xmm3); // rho = Re(rho) + Im(rho) + rho_rmi = _mm256_subs_epi16(xmm2,xmm3); // rho* = Re(rho) - Im(rho) + + // Compute the different rhos + rho_rpi_1_1 = _mm256_mulhi_epi16(rho_rpi, ONE_OVER_SQRT_42); + rho_rmi_1_1 = _mm256_mulhi_epi16(rho_rmi, ONE_OVER_SQRT_42); + rho_rpi_3_3 = _mm256_mulhi_epi16(rho_rpi, THREE_OVER_SQRT_42); + rho_rmi_3_3 = _mm256_mulhi_epi16(rho_rmi, THREE_OVER_SQRT_42); + rho_rpi_5_5 = _mm256_mulhi_epi16(rho_rpi, FIVE_OVER_SQRT_42); + rho_rmi_5_5 = _mm256_mulhi_epi16(rho_rmi, FIVE_OVER_SQRT_42); + rho_rpi_7_7 = _mm256_mulhi_epi16(rho_rpi, SEVEN_OVER_SQRT_42); + rho_rmi_7_7 = _mm256_mulhi_epi16(rho_rmi, SEVEN_OVER_SQRT_42); + + rho_rpi_5_5 = _mm256_slli_epi16(rho_rpi_5_5, 1); + rho_rmi_5_5 = _mm256_slli_epi16(rho_rmi_5_5, 1); + rho_rpi_7_7 = _mm256_slli_epi16(rho_rpi_7_7, 2); + rho_rmi_7_7 = _mm256_slli_epi16(rho_rmi_7_7, 2); + + xmm4 = _mm256_mulhi_epi16(xmm2, ONE_OVER_SQRT_42); + xmm5 = _mm256_mulhi_epi16(xmm3, ONE_OVER_SQRT_42); + xmm6 = _mm256_mulhi_epi16(xmm3, THREE_OVER_SQRT_42); + xmm7 = _mm256_mulhi_epi16(xmm3, FIVE_OVER_SQRT_42); + xmm8 = _mm256_mulhi_epi16(xmm3, SEVEN_OVER_SQRT_42); + xmm7 = _mm256_slli_epi16(xmm7, 1); + xmm8 = _mm256_slli_epi16(xmm8, 2); + + rho_rpi_1_3 = _mm256_adds_epi16(xmm4, xmm6); + rho_rmi_1_3 = _mm256_subs_epi16(xmm4, xmm6); + rho_rpi_1_5 = _mm256_adds_epi16(xmm4, xmm7); + rho_rmi_1_5 = _mm256_subs_epi16(xmm4, xmm7); + rho_rpi_1_7 = _mm256_adds_epi16(xmm4, xmm8); + rho_rmi_1_7 = _mm256_subs_epi16(xmm4, xmm8); + + xmm4 = _mm256_mulhi_epi16(xmm2, THREE_OVER_SQRT_42); + rho_rpi_3_1 = _mm256_adds_epi16(xmm4, xmm5); + rho_rmi_3_1 = _mm256_subs_epi16(xmm4, xmm5); + rho_rpi_3_5 = _mm256_adds_epi16(xmm4, xmm7); + rho_rmi_3_5 = _mm256_subs_epi16(xmm4, xmm7); + rho_rpi_3_7 = _mm256_adds_epi16(xmm4, xmm8); + rho_rmi_3_7 = _mm256_subs_epi16(xmm4, xmm8); + + xmm4 = _mm256_mulhi_epi16(xmm2, FIVE_OVER_SQRT_42); + xmm4 = _mm256_slli_epi16(xmm4, 1); + rho_rpi_5_1 = _mm256_adds_epi16(xmm4, xmm5); + rho_rmi_5_1 = _mm256_subs_epi16(xmm4, xmm5); + rho_rpi_5_3 = _mm256_adds_epi16(xmm4, xmm6); + rho_rmi_5_3 = _mm256_subs_epi16(xmm4, xmm6); + rho_rpi_5_7 = _mm256_adds_epi16(xmm4, xmm8); + rho_rmi_5_7 = _mm256_subs_epi16(xmm4, xmm8); + + xmm4 = _mm256_mulhi_epi16(xmm2, SEVEN_OVER_SQRT_42); + xmm4 = _mm256_slli_epi16(xmm4, 2); + rho_rpi_7_1 = _mm256_adds_epi16(xmm4, xmm5); + rho_rmi_7_1 = _mm256_subs_epi16(xmm4, xmm5); + rho_rpi_7_3 = _mm256_adds_epi16(xmm4, xmm6); + rho_rmi_7_3 = _mm256_subs_epi16(xmm4, xmm6); + rho_rpi_7_5 = _mm256_adds_epi16(xmm4, xmm7); + rho_rmi_7_5 = _mm256_subs_epi16(xmm4, xmm7); + + // Rearrange interfering MF output + /* + xmm0 = stream1_256i_in[i]; + xmm1 = stream1_256i_in[i+1]; + xmm0 = _mm256_shufflelo_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shufflehi_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm256_shuffle_epi32(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + + xmm1 = _mm256_shufflelo_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shufflehi_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm256_shuffle_epi32(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + + y1r = _mm256_unpacklo_epi64(xmm0, xmm1); + y1r = _mm256_permute4x64_epi64(y1r,0xd8); // Re(y1) + + y1i = _mm256_unpackhi_epi64(xmm0, xmm1); + y1i = _mm256_permute4x64_epi64(y1i,0xd8); // Im(y1) + */ + + seperate_real_imag_parts(&y1r, &y1i, stream1_256i_in[i], stream1_256i_in[i+1]); + + // Psi_r calculation from rho_rpi or rho_rmi + xmm0 = _mm256_broadcastw_epi16(_mm_set1_epi16(0));// ZERO for abs_pi16 + xmm2 = _mm256_subs_epi16(rho_rpi_7_7, y1r); + + psi_r_p7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_5, y1r); + psi_r_p7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_3, y1r); + psi_r_p7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_1, y1r); + psi_r_p7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_1, y1r); + psi_r_p7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_3, y1r); + psi_r_p7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_5, y1r); + psi_r_p7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_7, y1r); + psi_r_p7_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_7, y1r); + psi_r_p5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_5, y1r); + psi_r_p5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_3, y1r); + psi_r_p5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_1, y1r); + psi_r_p5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_1, y1r); + psi_r_p5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_3, y1r); + psi_r_p5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_5, y1r); + psi_r_p5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_7, y1r); + psi_r_p5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_7, y1r); + psi_r_p3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_5, y1r); + psi_r_p3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_3, y1r); + psi_r_p3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_1, y1r); + psi_r_p3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_1, y1r); + psi_r_p3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_3, y1r); + psi_r_p3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_5, y1r); + psi_r_p3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_7, y1r); + psi_r_p3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_7, y1r); + psi_r_p1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_5, y1r); + psi_r_p1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_3, y1r); + psi_r_p1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_1, y1r); + psi_r_p1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_1, y1r); + psi_r_p1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_3, y1r); + psi_r_p1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_5, y1r); + psi_r_p1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_7, y1r); + psi_r_p1_m7 = _mm256_abs_epi16(xmm2); + + xmm2 = _mm256_adds_epi16(rho_rmi_1_7, y1r); + psi_r_m1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_5, y1r); + psi_r_m1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_3, y1r); + psi_r_m1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_1, y1r); + psi_r_m1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_1, y1r); + psi_r_m1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_3, y1r); + psi_r_m1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_5, y1r); + psi_r_m1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_7, y1r); + psi_r_m1_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_7, y1r); + psi_r_m3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_5, y1r); + psi_r_m3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_3, y1r); + psi_r_m3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_1, y1r); + psi_r_m3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_1, y1r); + psi_r_m3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_3, y1r); + psi_r_m3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_5, y1r); + psi_r_m3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_7, y1r); + psi_r_m3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_7, y1r); + psi_r_m5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_5, y1r); + psi_r_m5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_3, y1r); + psi_r_m5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_1, y1r); + psi_r_m5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_1, y1r); + psi_r_m5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_3, y1r); + psi_r_m5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_5, y1r); + psi_r_m5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_7, y1r); + psi_r_m5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_7, y1r); + psi_r_m7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_5, y1r); + psi_r_m7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_3, y1r); + psi_r_m7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_1, y1r); + psi_r_m7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_1, y1r); + psi_r_m7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_3, y1r); + psi_r_m7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_5, y1r); + psi_r_m7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_7, y1r); + psi_r_m7_m7 = _mm256_abs_epi16(xmm2); + + // Psi_i calculation from rho_rpi or rho_rmi + xmm2 = _mm256_subs_epi16(rho_rmi_7_7, y1i); + psi_i_p7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_7, y1i); + psi_i_p7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_7, y1i); + psi_i_p7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_7, y1i); + psi_i_p7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_7, y1i); + psi_i_p7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_7, y1i); + psi_i_p7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_7, y1i); + psi_i_p7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_7, y1i); + psi_i_p7_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_5, y1i); + psi_i_p5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_5, y1i); + psi_i_p5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_5, y1i); + psi_i_p5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_5, y1i); + psi_i_p5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_5, y1i); + psi_i_p5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_5, y1i); + psi_i_p5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_5, y1i); + psi_i_p5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_5, y1i); + psi_i_p5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_3, y1i); + psi_i_p3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_3, y1i); + psi_i_p3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_3, y1i); + psi_i_p3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_3, y1i); + psi_i_p3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_3, y1i); + psi_i_p3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_3, y1i); + psi_i_p3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_3, y1i); + psi_i_p3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_3, y1i); + psi_i_p3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_7_1, y1i); + psi_i_p1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_5_1, y1i); + psi_i_p1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_3_1, y1i); + psi_i_p1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rmi_1_1, y1i); + psi_i_p1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_1_1, y1i); + psi_i_p1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_3_1, y1i); + psi_i_p1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_5_1, y1i); + psi_i_p1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rpi_7_1, y1i); + psi_i_p1_m7 = _mm256_abs_epi16(xmm2); + + xmm2 = _mm256_subs_epi16(rho_rpi_7_1, y1i); + psi_i_m1_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_1, y1i); + psi_i_m1_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_1, y1i); + psi_i_m1_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_1, y1i); + psi_i_m1_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_1, y1i); + psi_i_m1_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_1, y1i); + psi_i_m1_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_1, y1i); + psi_i_m1_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_1, y1i); + psi_i_m1_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_3, y1i); + psi_i_m3_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_3, y1i); + psi_i_m3_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_3, y1i); + psi_i_m3_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_3, y1i); + psi_i_m3_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_3, y1i); + psi_i_m3_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_3, y1i); + psi_i_m3_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_3, y1i); + psi_i_m3_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_3, y1i); + psi_i_m3_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_5, y1i); + psi_i_m5_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_5, y1i); + psi_i_m5_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_5, y1i); + psi_i_m5_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_5, y1i); + psi_i_m5_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_5, y1i); + psi_i_m5_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_5, y1i); + psi_i_m5_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_5, y1i); + psi_i_m5_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_5, y1i); + psi_i_m5_m7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_7_7, y1i); + psi_i_m7_p7 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_5_7, y1i); + psi_i_m7_p5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_3_7, y1i); + psi_i_m7_p3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_subs_epi16(rho_rpi_1_7, y1i); + psi_i_m7_p1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_1_7, y1i); + psi_i_m7_m1 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_3_7, y1i); + psi_i_m7_m3 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_5_7, y1i); + psi_i_m7_m5 = _mm256_abs_epi16(xmm2); + xmm2 = _mm256_adds_epi16(rho_rmi_7_7, y1i); + psi_i_m7_m7 = _mm256_abs_epi16(xmm2); + + /* + // Rearrange desired MF output + xmm0 = stream0_256i_in[i]; + xmm1 = stream0_256i_in[i+1]; + xmm0 = _mm_shufflelo_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm_shufflehi_epi16(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm0 = _mm_shuffle_epi32(xmm0,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm_shufflelo_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm_shufflehi_epi16(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm1 = _mm_shuffle_epi32(xmm1,0xd8); //_MM_SHUFFLE(0,2,1,3)); + //xmm0 = [Re(0,1) Re(2,3) Im(0,1) Im(2,3)] + //xmm1 = [Re(4,5) Re(6,7) Im(4,5) Im(6,7)] + y0r = _mm_unpacklo_epi64(xmm0,xmm1); // = [y0r(1),y0r(2),y0r(3),y0r(4)] + y0i = _mm_unpackhi_epi64(xmm0,xmm1); + */ + seperate_real_imag_parts(&y0r, &y0i, stream0_256i_in[i], stream0_256i_in[i+1]); + + // Rearrange desired channel magnitudes + // [|h|^2(1),|h|^2(1),|h|^2(2),|h|^2(2),...,,|h|^2(7),|h|^2(7)]*(2/sqrt(10)) + /* + xmm2 = ch_mag_256i[i]; + xmm3 = ch_mag_256i[i+1]; + xmm2 = _mm_shufflelo_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm_shufflehi_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm_shuffle_epi32(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm_shufflelo_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm_shufflehi_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm_shuffle_epi32(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + ch_mag_des = _mm_unpacklo_epi64(xmm2,xmm3); + */ + // xmm2 is dummy variable that contains the same values as ch_mag_des + seperate_real_imag_parts(&ch_mag_des, &xmm2, ch_mag_256i[i], ch_mag_256i[i+1]); + + + // Rearrange interfering channel magnitudes + /* + xmm2 = ch_mag_256i_i[i]; + xmm3 = ch_mag_256i_i[i+1]; + xmm2 = _mm_shufflelo_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm_shufflehi_epi16(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm2 = _mm_shuffle_epi32(xmm2,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm_shufflelo_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm_shufflehi_epi16(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + xmm3 = _mm_shuffle_epi32(xmm3,0xd8); //_MM_SHUFFLE(0,2,1,3)); + ch_mag_int = _mm_unpacklo_epi64(xmm2,xmm3); + */ + seperate_real_imag_parts(&ch_mag_int, &xmm2, ch_mag_256i_i[i], ch_mag_256i_i[i+1]); + + y0r_one_over_sqrt_21 = _mm256_mulhi_epi16(y0r, ONE_OVER_SQRT_42); + y0r_three_over_sqrt_21 = _mm256_mulhi_epi16(y0r, THREE_OVER_SQRT_42); + y0r_five_over_sqrt_21 = _mm256_mulhi_epi16(y0r, FIVE_OVER_SQRT_42); + y0r_five_over_sqrt_21 = _mm256_slli_epi16(y0r_five_over_sqrt_21, 1); + y0r_seven_over_sqrt_21 = _mm256_mulhi_epi16(y0r, SEVEN_OVER_SQRT_42); + y0r_seven_over_sqrt_21 = _mm256_slli_epi16(y0r_seven_over_sqrt_21, 2); // Q2.14 + + y0i_one_over_sqrt_21 = _mm256_mulhi_epi16(y0i, ONE_OVER_SQRT_42); + y0i_three_over_sqrt_21 = _mm256_mulhi_epi16(y0i, THREE_OVER_SQRT_42); + y0i_five_over_sqrt_21 = _mm256_mulhi_epi16(y0i, FIVE_OVER_SQRT_42); + y0i_five_over_sqrt_21 = _mm256_slli_epi16(y0i_five_over_sqrt_21, 1); + y0i_seven_over_sqrt_21 = _mm256_mulhi_epi16(y0i, SEVEN_OVER_SQRT_42); + y0i_seven_over_sqrt_21 = _mm256_slli_epi16(y0i_seven_over_sqrt_21, 2); // Q2.14 + + + y0_p_7_1 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_7_3 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_7_5 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_7_7 = _mm256_adds_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_p_5_1 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_5_3 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_5_5 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_5_7 = _mm256_adds_epi16(y0r_five_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_p_3_1 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_3_3 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_3_5 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_3_7 = _mm256_adds_epi16(y0r_three_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_p_1_1 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_one_over_sqrt_21); + y0_p_1_3 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_three_over_sqrt_21); + y0_p_1_5 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_five_over_sqrt_21); + y0_p_1_7 = _mm256_adds_epi16(y0r_one_over_sqrt_21, y0i_seven_over_sqrt_21); + + y0_m_1_1 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_1_3 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_1_5 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_1_7 = _mm256_subs_epi16(y0r_one_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_m_3_1 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_3_3 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_3_5 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_3_7 = _mm256_subs_epi16(y0r_three_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_m_5_1 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_5_3 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_5_5 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_5_7 = _mm256_subs_epi16(y0r_five_over_sqrt_21, y0i_seven_over_sqrt_21); + y0_m_7_1 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_one_over_sqrt_21); + y0_m_7_3 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_three_over_sqrt_21); + y0_m_7_5 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_five_over_sqrt_21); + y0_m_7_7 = _mm256_subs_epi16(y0r_seven_over_sqrt_21, y0i_seven_over_sqrt_21); + + // Detection of interference term + ch_mag_int_with_sigma2 = _mm256_srai_epi16(ch_mag_int, 1); // *2 + two_ch_mag_int_with_sigma2 = ch_mag_int; // *4 + three_ch_mag_int_with_sigma2 = _mm256_adds_epi16(ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2); // *6 + + interference_abs_64qam_epi16(psi_r_p7_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p7_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p7_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p5_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p5_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p3_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p3_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_p1_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_p1_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m1_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m1_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m3_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m3_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m5_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m5_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_r_m7_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_r_m7_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + + interference_abs_64qam_epi16(psi_i_p7_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p7_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p7_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p5_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p5_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p3_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p3_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_p1_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_p1_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m1_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m1_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m3_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m3_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m5_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m5_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_p7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_p7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_p5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_p5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_p3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_p3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_p1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_p1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_m1, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_m1, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_m3, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_m3, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_m5, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_m5, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + interference_abs_64qam_epi16(psi_i_m7_m7, ch_mag_int_with_sigma2, two_ch_mag_int_with_sigma2, three_ch_mag_int_with_sigma2, a_i_m7_m7, ONE_OVER_SQRT_2_42, THREE_OVER_SQRT_2_42, FIVE_OVER_SQRT_2_42, + SEVEN_OVER_SQRT_2_42); + + // Calculation of a group of two terms in the bit metric involving product of psi and interference + prodsum_psi_a_epi16(psi_r_p7_p7, a_r_p7_p7, psi_i_p7_p7, a_i_p7_p7, psi_a_p7_p7); + prodsum_psi_a_epi16(psi_r_p7_p5, a_r_p7_p5, psi_i_p7_p5, a_i_p7_p5, psi_a_p7_p5); + prodsum_psi_a_epi16(psi_r_p7_p3, a_r_p7_p3, psi_i_p7_p3, a_i_p7_p3, psi_a_p7_p3); + prodsum_psi_a_epi16(psi_r_p7_p1, a_r_p7_p1, psi_i_p7_p1, a_i_p7_p1, psi_a_p7_p1); + prodsum_psi_a_epi16(psi_r_p7_m1, a_r_p7_m1, psi_i_p7_m1, a_i_p7_m1, psi_a_p7_m1); + prodsum_psi_a_epi16(psi_r_p7_m3, a_r_p7_m3, psi_i_p7_m3, a_i_p7_m3, psi_a_p7_m3); + prodsum_psi_a_epi16(psi_r_p7_m5, a_r_p7_m5, psi_i_p7_m5, a_i_p7_m5, psi_a_p7_m5); + prodsum_psi_a_epi16(psi_r_p7_m7, a_r_p7_m7, psi_i_p7_m7, a_i_p7_m7, psi_a_p7_m7); + prodsum_psi_a_epi16(psi_r_p5_p7, a_r_p5_p7, psi_i_p5_p7, a_i_p5_p7, psi_a_p5_p7); + prodsum_psi_a_epi16(psi_r_p5_p5, a_r_p5_p5, psi_i_p5_p5, a_i_p5_p5, psi_a_p5_p5); + prodsum_psi_a_epi16(psi_r_p5_p3, a_r_p5_p3, psi_i_p5_p3, a_i_p5_p3, psi_a_p5_p3); + prodsum_psi_a_epi16(psi_r_p5_p1, a_r_p5_p1, psi_i_p5_p1, a_i_p5_p1, psi_a_p5_p1); + prodsum_psi_a_epi16(psi_r_p5_m1, a_r_p5_m1, psi_i_p5_m1, a_i_p5_m1, psi_a_p5_m1); + prodsum_psi_a_epi16(psi_r_p5_m3, a_r_p5_m3, psi_i_p5_m3, a_i_p5_m3, psi_a_p5_m3); + prodsum_psi_a_epi16(psi_r_p5_m5, a_r_p5_m5, psi_i_p5_m5, a_i_p5_m5, psi_a_p5_m5); + prodsum_psi_a_epi16(psi_r_p5_m7, a_r_p5_m7, psi_i_p5_m7, a_i_p5_m7, psi_a_p5_m7); + prodsum_psi_a_epi16(psi_r_p3_p7, a_r_p3_p7, psi_i_p3_p7, a_i_p3_p7, psi_a_p3_p7); + prodsum_psi_a_epi16(psi_r_p3_p5, a_r_p3_p5, psi_i_p3_p5, a_i_p3_p5, psi_a_p3_p5); + prodsum_psi_a_epi16(psi_r_p3_p3, a_r_p3_p3, psi_i_p3_p3, a_i_p3_p3, psi_a_p3_p3); + prodsum_psi_a_epi16(psi_r_p3_p1, a_r_p3_p1, psi_i_p3_p1, a_i_p3_p1, psi_a_p3_p1); + prodsum_psi_a_epi16(psi_r_p3_m1, a_r_p3_m1, psi_i_p3_m1, a_i_p3_m1, psi_a_p3_m1); + prodsum_psi_a_epi16(psi_r_p3_m3, a_r_p3_m3, psi_i_p3_m3, a_i_p3_m3, psi_a_p3_m3); + prodsum_psi_a_epi16(psi_r_p3_m5, a_r_p3_m5, psi_i_p3_m5, a_i_p3_m5, psi_a_p3_m5); + prodsum_psi_a_epi16(psi_r_p3_m7, a_r_p3_m7, psi_i_p3_m7, a_i_p3_m7, psi_a_p3_m7); + prodsum_psi_a_epi16(psi_r_p1_p7, a_r_p1_p7, psi_i_p1_p7, a_i_p1_p7, psi_a_p1_p7); + prodsum_psi_a_epi16(psi_r_p1_p5, a_r_p1_p5, psi_i_p1_p5, a_i_p1_p5, psi_a_p1_p5); + prodsum_psi_a_epi16(psi_r_p1_p3, a_r_p1_p3, psi_i_p1_p3, a_i_p1_p3, psi_a_p1_p3); + prodsum_psi_a_epi16(psi_r_p1_p1, a_r_p1_p1, psi_i_p1_p1, a_i_p1_p1, psi_a_p1_p1); + prodsum_psi_a_epi16(psi_r_p1_m1, a_r_p1_m1, psi_i_p1_m1, a_i_p1_m1, psi_a_p1_m1); + prodsum_psi_a_epi16(psi_r_p1_m3, a_r_p1_m3, psi_i_p1_m3, a_i_p1_m3, psi_a_p1_m3); + prodsum_psi_a_epi16(psi_r_p1_m5, a_r_p1_m5, psi_i_p1_m5, a_i_p1_m5, psi_a_p1_m5); + prodsum_psi_a_epi16(psi_r_p1_m7, a_r_p1_m7, psi_i_p1_m7, a_i_p1_m7, psi_a_p1_m7); + prodsum_psi_a_epi16(psi_r_m1_p7, a_r_m1_p7, psi_i_m1_p7, a_i_m1_p7, psi_a_m1_p7); + prodsum_psi_a_epi16(psi_r_m1_p5, a_r_m1_p5, psi_i_m1_p5, a_i_m1_p5, psi_a_m1_p5); + prodsum_psi_a_epi16(psi_r_m1_p3, a_r_m1_p3, psi_i_m1_p3, a_i_m1_p3, psi_a_m1_p3); + prodsum_psi_a_epi16(psi_r_m1_p1, a_r_m1_p1, psi_i_m1_p1, a_i_m1_p1, psi_a_m1_p1); + prodsum_psi_a_epi16(psi_r_m1_m1, a_r_m1_m1, psi_i_m1_m1, a_i_m1_m1, psi_a_m1_m1); + prodsum_psi_a_epi16(psi_r_m1_m3, a_r_m1_m3, psi_i_m1_m3, a_i_m1_m3, psi_a_m1_m3); + prodsum_psi_a_epi16(psi_r_m1_m5, a_r_m1_m5, psi_i_m1_m5, a_i_m1_m5, psi_a_m1_m5); + prodsum_psi_a_epi16(psi_r_m1_m7, a_r_m1_m7, psi_i_m1_m7, a_i_m1_m7, psi_a_m1_m7); + prodsum_psi_a_epi16(psi_r_m3_p7, a_r_m3_p7, psi_i_m3_p7, a_i_m3_p7, psi_a_m3_p7); + prodsum_psi_a_epi16(psi_r_m3_p5, a_r_m3_p5, psi_i_m3_p5, a_i_m3_p5, psi_a_m3_p5); + prodsum_psi_a_epi16(psi_r_m3_p3, a_r_m3_p3, psi_i_m3_p3, a_i_m3_p3, psi_a_m3_p3); + prodsum_psi_a_epi16(psi_r_m3_p1, a_r_m3_p1, psi_i_m3_p1, a_i_m3_p1, psi_a_m3_p1); + prodsum_psi_a_epi16(psi_r_m3_m1, a_r_m3_m1, psi_i_m3_m1, a_i_m3_m1, psi_a_m3_m1); + prodsum_psi_a_epi16(psi_r_m3_m3, a_r_m3_m3, psi_i_m3_m3, a_i_m3_m3, psi_a_m3_m3); + prodsum_psi_a_epi16(psi_r_m3_m5, a_r_m3_m5, psi_i_m3_m5, a_i_m3_m5, psi_a_m3_m5); + prodsum_psi_a_epi16(psi_r_m3_m7, a_r_m3_m7, psi_i_m3_m7, a_i_m3_m7, psi_a_m3_m7); + prodsum_psi_a_epi16(psi_r_m5_p7, a_r_m5_p7, psi_i_m5_p7, a_i_m5_p7, psi_a_m5_p7); + prodsum_psi_a_epi16(psi_r_m5_p5, a_r_m5_p5, psi_i_m5_p5, a_i_m5_p5, psi_a_m5_p5); + prodsum_psi_a_epi16(psi_r_m5_p3, a_r_m5_p3, psi_i_m5_p3, a_i_m5_p3, psi_a_m5_p3); + prodsum_psi_a_epi16(psi_r_m5_p1, a_r_m5_p1, psi_i_m5_p1, a_i_m5_p1, psi_a_m5_p1); + prodsum_psi_a_epi16(psi_r_m5_m1, a_r_m5_m1, psi_i_m5_m1, a_i_m5_m1, psi_a_m5_m1); + prodsum_psi_a_epi16(psi_r_m5_m3, a_r_m5_m3, psi_i_m5_m3, a_i_m5_m3, psi_a_m5_m3); + prodsum_psi_a_epi16(psi_r_m5_m5, a_r_m5_m5, psi_i_m5_m5, a_i_m5_m5, psi_a_m5_m5); + prodsum_psi_a_epi16(psi_r_m5_m7, a_r_m5_m7, psi_i_m5_m7, a_i_m5_m7, psi_a_m5_m7); + prodsum_psi_a_epi16(psi_r_m7_p7, a_r_m7_p7, psi_i_m7_p7, a_i_m7_p7, psi_a_m7_p7); + prodsum_psi_a_epi16(psi_r_m7_p5, a_r_m7_p5, psi_i_m7_p5, a_i_m7_p5, psi_a_m7_p5); + prodsum_psi_a_epi16(psi_r_m7_p3, a_r_m7_p3, psi_i_m7_p3, a_i_m7_p3, psi_a_m7_p3); + prodsum_psi_a_epi16(psi_r_m7_p1, a_r_m7_p1, psi_i_m7_p1, a_i_m7_p1, psi_a_m7_p1); + prodsum_psi_a_epi16(psi_r_m7_m1, a_r_m7_m1, psi_i_m7_m1, a_i_m7_m1, psi_a_m7_m1); + prodsum_psi_a_epi16(psi_r_m7_m3, a_r_m7_m3, psi_i_m7_m3, a_i_m7_m3, psi_a_m7_m3); + prodsum_psi_a_epi16(psi_r_m7_m5, a_r_m7_m5, psi_i_m7_m5, a_i_m7_m5, psi_a_m7_m5); + prodsum_psi_a_epi16(psi_r_m7_m7, a_r_m7_m7, psi_i_m7_m7, a_i_m7_m7, psi_a_m7_m7); + + // Multiply by sqrt(2) + psi_a_p7_p7 = _mm256_mulhi_epi16(psi_a_p7_p7, ONE_OVER_SQRT_2); + psi_a_p7_p7 = _mm256_slli_epi16(psi_a_p7_p7, 2); + psi_a_p7_p5 = _mm256_mulhi_epi16(psi_a_p7_p5, ONE_OVER_SQRT_2); + psi_a_p7_p5 = _mm256_slli_epi16(psi_a_p7_p5, 2); + psi_a_p7_p3 = _mm256_mulhi_epi16(psi_a_p7_p3, ONE_OVER_SQRT_2); + psi_a_p7_p3 = _mm256_slli_epi16(psi_a_p7_p3, 2); + psi_a_p7_p1 = _mm256_mulhi_epi16(psi_a_p7_p1, ONE_OVER_SQRT_2); + psi_a_p7_p1 = _mm256_slli_epi16(psi_a_p7_p1, 2); + psi_a_p7_m1 = _mm256_mulhi_epi16(psi_a_p7_m1, ONE_OVER_SQRT_2); + psi_a_p7_m1 = _mm256_slli_epi16(psi_a_p7_m1, 2); + psi_a_p7_m3 = _mm256_mulhi_epi16(psi_a_p7_m3, ONE_OVER_SQRT_2); + psi_a_p7_m3 = _mm256_slli_epi16(psi_a_p7_m3, 2); + psi_a_p7_m5 = _mm256_mulhi_epi16(psi_a_p7_m5, ONE_OVER_SQRT_2); + psi_a_p7_m5 = _mm256_slli_epi16(psi_a_p7_m5, 2); + psi_a_p7_m7 = _mm256_mulhi_epi16(psi_a_p7_m7, ONE_OVER_SQRT_2); + psi_a_p7_m7 = _mm256_slli_epi16(psi_a_p7_m7, 2); + psi_a_p5_p7 = _mm256_mulhi_epi16(psi_a_p5_p7, ONE_OVER_SQRT_2); + psi_a_p5_p7 = _mm256_slli_epi16(psi_a_p5_p7, 2); + psi_a_p5_p5 = _mm256_mulhi_epi16(psi_a_p5_p5, ONE_OVER_SQRT_2); + psi_a_p5_p5 = _mm256_slli_epi16(psi_a_p5_p5, 2); + psi_a_p5_p3 = _mm256_mulhi_epi16(psi_a_p5_p3, ONE_OVER_SQRT_2); + psi_a_p5_p3 = _mm256_slli_epi16(psi_a_p5_p3, 2); + psi_a_p5_p1 = _mm256_mulhi_epi16(psi_a_p5_p1, ONE_OVER_SQRT_2); + psi_a_p5_p1 = _mm256_slli_epi16(psi_a_p5_p1, 2); + psi_a_p5_m1 = _mm256_mulhi_epi16(psi_a_p5_m1, ONE_OVER_SQRT_2); + psi_a_p5_m1 = _mm256_slli_epi16(psi_a_p5_m1, 2); + psi_a_p5_m3 = _mm256_mulhi_epi16(psi_a_p5_m3, ONE_OVER_SQRT_2); + psi_a_p5_m3 = _mm256_slli_epi16(psi_a_p5_m3, 2); + psi_a_p5_m5 = _mm256_mulhi_epi16(psi_a_p5_m5, ONE_OVER_SQRT_2); + psi_a_p5_m5 = _mm256_slli_epi16(psi_a_p5_m5, 2); + psi_a_p5_m7 = _mm256_mulhi_epi16(psi_a_p5_m7, ONE_OVER_SQRT_2); + psi_a_p5_m7 = _mm256_slli_epi16(psi_a_p5_m7, 2); + psi_a_p3_p7 = _mm256_mulhi_epi16(psi_a_p3_p7, ONE_OVER_SQRT_2); + psi_a_p3_p7 = _mm256_slli_epi16(psi_a_p3_p7, 2); + psi_a_p3_p5 = _mm256_mulhi_epi16(psi_a_p3_p5, ONE_OVER_SQRT_2); + psi_a_p3_p5 = _mm256_slli_epi16(psi_a_p3_p5, 2); + psi_a_p3_p3 = _mm256_mulhi_epi16(psi_a_p3_p3, ONE_OVER_SQRT_2); + psi_a_p3_p3 = _mm256_slli_epi16(psi_a_p3_p3, 2); + psi_a_p3_p1 = _mm256_mulhi_epi16(psi_a_p3_p1, ONE_OVER_SQRT_2); + psi_a_p3_p1 = _mm256_slli_epi16(psi_a_p3_p1, 2); + psi_a_p3_m1 = _mm256_mulhi_epi16(psi_a_p3_m1, ONE_OVER_SQRT_2); + psi_a_p3_m1 = _mm256_slli_epi16(psi_a_p3_m1, 2); + psi_a_p3_m3 = _mm256_mulhi_epi16(psi_a_p3_m3, ONE_OVER_SQRT_2); + psi_a_p3_m3 = _mm256_slli_epi16(psi_a_p3_m3, 2); + psi_a_p3_m5 = _mm256_mulhi_epi16(psi_a_p3_m5, ONE_OVER_SQRT_2); + psi_a_p3_m5 = _mm256_slli_epi16(psi_a_p3_m5, 2); + psi_a_p3_m7 = _mm256_mulhi_epi16(psi_a_p3_m7, ONE_OVER_SQRT_2); + psi_a_p3_m7 = _mm256_slli_epi16(psi_a_p3_m7, 2); + psi_a_p1_p7 = _mm256_mulhi_epi16(psi_a_p1_p7, ONE_OVER_SQRT_2); + psi_a_p1_p7 = _mm256_slli_epi16(psi_a_p1_p7, 2); + psi_a_p1_p5 = _mm256_mulhi_epi16(psi_a_p1_p5, ONE_OVER_SQRT_2); + psi_a_p1_p5 = _mm256_slli_epi16(psi_a_p1_p5, 2); + psi_a_p1_p3 = _mm256_mulhi_epi16(psi_a_p1_p3, ONE_OVER_SQRT_2); + psi_a_p1_p3 = _mm256_slli_epi16(psi_a_p1_p3, 2); + psi_a_p1_p1 = _mm256_mulhi_epi16(psi_a_p1_p1, ONE_OVER_SQRT_2); + psi_a_p1_p1 = _mm256_slli_epi16(psi_a_p1_p1, 2); + psi_a_p1_m1 = _mm256_mulhi_epi16(psi_a_p1_m1, ONE_OVER_SQRT_2); + psi_a_p1_m1 = _mm256_slli_epi16(psi_a_p1_m1, 2); + psi_a_p1_m3 = _mm256_mulhi_epi16(psi_a_p1_m3, ONE_OVER_SQRT_2); + psi_a_p1_m3 = _mm256_slli_epi16(psi_a_p1_m3, 2); + psi_a_p1_m5 = _mm256_mulhi_epi16(psi_a_p1_m5, ONE_OVER_SQRT_2); + psi_a_p1_m5 = _mm256_slli_epi16(psi_a_p1_m5, 2); + psi_a_p1_m7 = _mm256_mulhi_epi16(psi_a_p1_m7, ONE_OVER_SQRT_2); + psi_a_p1_m7 = _mm256_slli_epi16(psi_a_p1_m7, 2); + psi_a_m1_p7 = _mm256_mulhi_epi16(psi_a_m1_p7, ONE_OVER_SQRT_2); + psi_a_m1_p7 = _mm256_slli_epi16(psi_a_m1_p7, 2); + psi_a_m1_p5 = _mm256_mulhi_epi16(psi_a_m1_p5, ONE_OVER_SQRT_2); + psi_a_m1_p5 = _mm256_slli_epi16(psi_a_m1_p5, 2); + psi_a_m1_p3 = _mm256_mulhi_epi16(psi_a_m1_p3, ONE_OVER_SQRT_2); + psi_a_m1_p3 = _mm256_slli_epi16(psi_a_m1_p3, 2); + psi_a_m1_p1 = _mm256_mulhi_epi16(psi_a_m1_p1, ONE_OVER_SQRT_2); + psi_a_m1_p1 = _mm256_slli_epi16(psi_a_m1_p1, 2); + psi_a_m1_m1 = _mm256_mulhi_epi16(psi_a_m1_m1, ONE_OVER_SQRT_2); + psi_a_m1_m1 = _mm256_slli_epi16(psi_a_m1_m1, 2); + psi_a_m1_m3 = _mm256_mulhi_epi16(psi_a_m1_m3, ONE_OVER_SQRT_2); + psi_a_m1_m3 = _mm256_slli_epi16(psi_a_m1_m3, 2); + psi_a_m1_m5 = _mm256_mulhi_epi16(psi_a_m1_m5, ONE_OVER_SQRT_2); + psi_a_m1_m5 = _mm256_slli_epi16(psi_a_m1_m5, 2); + psi_a_m1_m7 = _mm256_mulhi_epi16(psi_a_m1_m7, ONE_OVER_SQRT_2); + psi_a_m1_m7 = _mm256_slli_epi16(psi_a_m1_m7, 2); + psi_a_m3_p7 = _mm256_mulhi_epi16(psi_a_m3_p7, ONE_OVER_SQRT_2); + psi_a_m3_p7 = _mm256_slli_epi16(psi_a_m3_p7, 2); + psi_a_m3_p5 = _mm256_mulhi_epi16(psi_a_m3_p5, ONE_OVER_SQRT_2); + psi_a_m3_p5 = _mm256_slli_epi16(psi_a_m3_p5, 2); + psi_a_m3_p3 = _mm256_mulhi_epi16(psi_a_m3_p3, ONE_OVER_SQRT_2); + psi_a_m3_p3 = _mm256_slli_epi16(psi_a_m3_p3, 2); + psi_a_m3_p1 = _mm256_mulhi_epi16(psi_a_m3_p1, ONE_OVER_SQRT_2); + psi_a_m3_p1 = _mm256_slli_epi16(psi_a_m3_p1, 2); + psi_a_m3_m1 = _mm256_mulhi_epi16(psi_a_m3_m1, ONE_OVER_SQRT_2); + psi_a_m3_m1 = _mm256_slli_epi16(psi_a_m3_m1, 2); + psi_a_m3_m3 = _mm256_mulhi_epi16(psi_a_m3_m3, ONE_OVER_SQRT_2); + psi_a_m3_m3 = _mm256_slli_epi16(psi_a_m3_m3, 2); + psi_a_m3_m5 = _mm256_mulhi_epi16(psi_a_m3_m5, ONE_OVER_SQRT_2); + psi_a_m3_m5 = _mm256_slli_epi16(psi_a_m3_m5, 2); + psi_a_m3_m7 = _mm256_mulhi_epi16(psi_a_m3_m7, ONE_OVER_SQRT_2); + psi_a_m3_m7 = _mm256_slli_epi16(psi_a_m3_m7, 2); + psi_a_m5_p7 = _mm256_mulhi_epi16(psi_a_m5_p7, ONE_OVER_SQRT_2); + psi_a_m5_p7 = _mm256_slli_epi16(psi_a_m5_p7, 2); + psi_a_m5_p5 = _mm256_mulhi_epi16(psi_a_m5_p5, ONE_OVER_SQRT_2); + psi_a_m5_p5 = _mm256_slli_epi16(psi_a_m5_p5, 2); + psi_a_m5_p3 = _mm256_mulhi_epi16(psi_a_m5_p3, ONE_OVER_SQRT_2); + psi_a_m5_p3 = _mm256_slli_epi16(psi_a_m5_p3, 2); + psi_a_m5_p1 = _mm256_mulhi_epi16(psi_a_m5_p1, ONE_OVER_SQRT_2); + psi_a_m5_p1 = _mm256_slli_epi16(psi_a_m5_p1, 2); + psi_a_m5_m1 = _mm256_mulhi_epi16(psi_a_m5_m1, ONE_OVER_SQRT_2); + psi_a_m5_m1 = _mm256_slli_epi16(psi_a_m5_m1, 2); + psi_a_m5_m3 = _mm256_mulhi_epi16(psi_a_m5_m3, ONE_OVER_SQRT_2); + psi_a_m5_m3 = _mm256_slli_epi16(psi_a_m5_m3, 2); + psi_a_m5_m5 = _mm256_mulhi_epi16(psi_a_m5_m5, ONE_OVER_SQRT_2); + psi_a_m5_m5 = _mm256_slli_epi16(psi_a_m5_m5, 2); + psi_a_m5_m7 = _mm256_mulhi_epi16(psi_a_m5_m7, ONE_OVER_SQRT_2); + psi_a_m5_m7 = _mm256_slli_epi16(psi_a_m5_m7, 2); + psi_a_m7_p7 = _mm256_mulhi_epi16(psi_a_m7_p7, ONE_OVER_SQRT_2); + psi_a_m7_p7 = _mm256_slli_epi16(psi_a_m7_p7, 2); + psi_a_m7_p5 = _mm256_mulhi_epi16(psi_a_m7_p5, ONE_OVER_SQRT_2); + psi_a_m7_p5 = _mm256_slli_epi16(psi_a_m7_p5, 2); + psi_a_m7_p3 = _mm256_mulhi_epi16(psi_a_m7_p3, ONE_OVER_SQRT_2); + psi_a_m7_p3 = _mm256_slli_epi16(psi_a_m7_p3, 2); + psi_a_m7_p1 = _mm256_mulhi_epi16(psi_a_m7_p1, ONE_OVER_SQRT_2); + psi_a_m7_p1 = _mm256_slli_epi16(psi_a_m7_p1, 2); + psi_a_m7_m1 = _mm256_mulhi_epi16(psi_a_m7_m1, ONE_OVER_SQRT_2); + psi_a_m7_m1 = _mm256_slli_epi16(psi_a_m7_m1, 2); + psi_a_m7_m3 = _mm256_mulhi_epi16(psi_a_m7_m3, ONE_OVER_SQRT_2); + psi_a_m7_m3 = _mm256_slli_epi16(psi_a_m7_m3, 2); + psi_a_m7_m5 = _mm256_mulhi_epi16(psi_a_m7_m5, ONE_OVER_SQRT_2); + psi_a_m7_m5 = _mm256_slli_epi16(psi_a_m7_m5, 2); + psi_a_m7_m7 = _mm256_mulhi_epi16(psi_a_m7_m7, ONE_OVER_SQRT_2); + psi_a_m7_m7 = _mm256_slli_epi16(psi_a_m7_m7, 2); + + // Calculation of a group of two terms in the bit metric involving squares of interference + square_a_64qam_epi16(a_r_p7_p7, a_i_p7_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p7); + square_a_64qam_epi16(a_r_p7_p5, a_i_p7_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p5); + square_a_64qam_epi16(a_r_p7_p3, a_i_p7_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p3); + square_a_64qam_epi16(a_r_p7_p1, a_i_p7_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_p1); + square_a_64qam_epi16(a_r_p7_m1, a_i_p7_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m1); + square_a_64qam_epi16(a_r_p7_m3, a_i_p7_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m3); + square_a_64qam_epi16(a_r_p7_m5, a_i_p7_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m5); + square_a_64qam_epi16(a_r_p7_m7, a_i_p7_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p7_m7); + square_a_64qam_epi16(a_r_p5_p7, a_i_p5_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p7); + square_a_64qam_epi16(a_r_p5_p5, a_i_p5_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p5); + square_a_64qam_epi16(a_r_p5_p3, a_i_p5_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p3); + square_a_64qam_epi16(a_r_p5_p1, a_i_p5_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_p1); + square_a_64qam_epi16(a_r_p5_m1, a_i_p5_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m1); + square_a_64qam_epi16(a_r_p5_m3, a_i_p5_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m3); + square_a_64qam_epi16(a_r_p5_m5, a_i_p5_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m5); + square_a_64qam_epi16(a_r_p5_m7, a_i_p5_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p5_m7); + square_a_64qam_epi16(a_r_p3_p7, a_i_p3_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p7); + square_a_64qam_epi16(a_r_p3_p5, a_i_p3_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p5); + square_a_64qam_epi16(a_r_p3_p3, a_i_p3_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p3); + square_a_64qam_epi16(a_r_p3_p1, a_i_p3_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_p1); + square_a_64qam_epi16(a_r_p3_m1, a_i_p3_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m1); + square_a_64qam_epi16(a_r_p3_m3, a_i_p3_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m3); + square_a_64qam_epi16(a_r_p3_m5, a_i_p3_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m5); + square_a_64qam_epi16(a_r_p3_m7, a_i_p3_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p3_m7); + square_a_64qam_epi16(a_r_p1_p7, a_i_p1_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p7); + square_a_64qam_epi16(a_r_p1_p5, a_i_p1_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p5); + square_a_64qam_epi16(a_r_p1_p3, a_i_p1_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p3); + square_a_64qam_epi16(a_r_p1_p1, a_i_p1_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_p1); + square_a_64qam_epi16(a_r_p1_m1, a_i_p1_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m1); + square_a_64qam_epi16(a_r_p1_m3, a_i_p1_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m3); + square_a_64qam_epi16(a_r_p1_m5, a_i_p1_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m5); + square_a_64qam_epi16(a_r_p1_m7, a_i_p1_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_p1_m7); + square_a_64qam_epi16(a_r_m1_p7, a_i_m1_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p7); + square_a_64qam_epi16(a_r_m1_p5, a_i_m1_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p5); + square_a_64qam_epi16(a_r_m1_p3, a_i_m1_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p3); + square_a_64qam_epi16(a_r_m1_p1, a_i_m1_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_p1); + square_a_64qam_epi16(a_r_m1_m1, a_i_m1_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m1); + square_a_64qam_epi16(a_r_m1_m3, a_i_m1_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m3); + square_a_64qam_epi16(a_r_m1_m5, a_i_m1_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m5); + square_a_64qam_epi16(a_r_m1_m7, a_i_m1_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m1_m7); + square_a_64qam_epi16(a_r_m3_p7, a_i_m3_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p7); + square_a_64qam_epi16(a_r_m3_p5, a_i_m3_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p5); + square_a_64qam_epi16(a_r_m3_p3, a_i_m3_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p3); + square_a_64qam_epi16(a_r_m3_p1, a_i_m3_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_p1); + square_a_64qam_epi16(a_r_m3_m1, a_i_m3_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m1); + square_a_64qam_epi16(a_r_m3_m3, a_i_m3_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m3); + square_a_64qam_epi16(a_r_m3_m5, a_i_m3_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m5); + square_a_64qam_epi16(a_r_m3_m7, a_i_m3_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m3_m7); + square_a_64qam_epi16(a_r_m5_p7, a_i_m5_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p7); + square_a_64qam_epi16(a_r_m5_p5, a_i_m5_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p5); + square_a_64qam_epi16(a_r_m5_p3, a_i_m5_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p3); + square_a_64qam_epi16(a_r_m5_p1, a_i_m5_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_p1); + square_a_64qam_epi16(a_r_m5_m1, a_i_m5_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m1); + square_a_64qam_epi16(a_r_m5_m3, a_i_m5_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m3); + square_a_64qam_epi16(a_r_m5_m5, a_i_m5_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m5); + square_a_64qam_epi16(a_r_m5_m7, a_i_m5_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m5_m7); + square_a_64qam_epi16(a_r_m7_p7, a_i_m7_p7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p7); + square_a_64qam_epi16(a_r_m7_p5, a_i_m7_p5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p5); + square_a_64qam_epi16(a_r_m7_p3, a_i_m7_p3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p3); + square_a_64qam_epi16(a_r_m7_p1, a_i_m7_p1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_p1); + square_a_64qam_epi16(a_r_m7_m1, a_i_m7_m1, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m1); + square_a_64qam_epi16(a_r_m7_m3, a_i_m7_m3, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m3); + square_a_64qam_epi16(a_r_m7_m5, a_i_m7_m5, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m5); + square_a_64qam_epi16(a_r_m7_m7, a_i_m7_m7, ch_mag_int, SQRT_42_OVER_FOUR, a_sq_m7_m7); + + // Computing different multiples of ||h0||^2 + // x=1, y=1 + ch_mag_2_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,ONE_OVER_FOUR_SQRT_42); + ch_mag_2_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_2_over_42_with_sigma2,1); + // x=1, y=3 + ch_mag_10_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,FIVE_OVER_FOUR_SQRT_42); + ch_mag_10_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_10_over_42_with_sigma2,1); + // x=1, x=5 + ch_mag_26_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,THIRTEEN_OVER_FOUR_SQRT_42); + ch_mag_26_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_26_over_42_with_sigma2,1); + // x=1, y=7 + ch_mag_50_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,TWENTYFIVE_OVER_FOUR_SQRT_42); + ch_mag_50_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_50_over_42_with_sigma2,1); + // x=3, y=3 + ch_mag_18_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,NINE_OVER_FOUR_SQRT_42); + ch_mag_18_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_18_over_42_with_sigma2,1); + // x=3, y=5 + ch_mag_34_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,SEVENTEEN_OVER_FOUR_SQRT_42); + ch_mag_34_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_34_over_42_with_sigma2,1); + // x=3, y=7 + ch_mag_58_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,TWENTYNINE_OVER_FOUR_SQRT_42); + ch_mag_58_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_58_over_42_with_sigma2,2); + // x=5, y=5 + ch_mag_50_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,TWENTYFIVE_OVER_FOUR_SQRT_42); + ch_mag_50_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_50_over_42_with_sigma2,1); + // x=5, y=7 + ch_mag_74_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,THIRTYSEVEN_OVER_FOUR_SQRT_42); + ch_mag_74_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_74_over_42_with_sigma2,2); + // x=7, y=7 + ch_mag_98_over_42_with_sigma2 = _mm256_mulhi_epi16(ch_mag_des,FORTYNINE_OVER_FOUR_SQRT_42); + ch_mag_98_over_42_with_sigma2 = _mm256_slli_epi16(ch_mag_98_over_42_with_sigma2,2); + + // Computing Metrics + xmm0 = _mm256_subs_epi16(psi_a_p7_p7, a_sq_p7_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_7); + bit_met_p7_p7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_p5, a_sq_p7_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_5); + bit_met_p7_p5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_p3, a_sq_p7_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_3); + bit_met_p7_p3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_p1, a_sq_p7_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_7_1); + bit_met_p7_p1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m1, a_sq_p7_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_1); + bit_met_p7_m1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m3, a_sq_p7_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_3); + bit_met_p7_m3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m5, a_sq_p7_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_5); + bit_met_p7_m5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p7_m7, a_sq_p7_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_7_7); + bit_met_p7_m7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p7, a_sq_p5_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_7); + bit_met_p5_p7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p5, a_sq_p5_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_5); + bit_met_p5_p5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p3, a_sq_p5_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_3); + bit_met_p5_p3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_p1, a_sq_p5_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_5_1); + bit_met_p5_p1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m1, a_sq_p5_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_1); + bit_met_p5_m1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m3, a_sq_p5_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_3); + bit_met_p5_m3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m5, a_sq_p5_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_5); + bit_met_p5_m5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p5_m7, a_sq_p5_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_5_7); + bit_met_p5_m7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p7, a_sq_p3_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_7); + bit_met_p3_p7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p5, a_sq_p3_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_5); + bit_met_p3_p5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p3, a_sq_p3_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_3); + bit_met_p3_p3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_p1, a_sq_p3_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_3_1); + bit_met_p3_p1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m1, a_sq_p3_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_1); + bit_met_p3_m1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m3, a_sq_p3_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_3); + bit_met_p3_m3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m5, a_sq_p3_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_5); + bit_met_p3_m5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p3_m7, a_sq_p3_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_3_7); + bit_met_p3_m7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p7, a_sq_p1_p7); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_7); + bit_met_p1_p7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p5, a_sq_p1_p5); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_5); + bit_met_p1_p5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p3, a_sq_p1_p3); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_3); + bit_met_p1_p3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_p1, a_sq_p1_p1); + xmm1 = _mm256_adds_epi16(xmm0, y0_p_1_1); + bit_met_p1_p1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m1, a_sq_p1_m1); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_1); + bit_met_p1_m1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m3, a_sq_p1_m3); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_3); + bit_met_p1_m3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m5, a_sq_p1_m5); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_5); + bit_met_p1_m5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_p1_m7, a_sq_p1_m7); + xmm1 = _mm256_adds_epi16(xmm0, y0_m_1_7); + bit_met_p1_m7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + + xmm0 = _mm256_subs_epi16(psi_a_m1_p7, a_sq_m1_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_7); + bit_met_m1_p7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_p5, a_sq_m1_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_5); + bit_met_m1_p5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_p3, a_sq_m1_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_3); + bit_met_m1_p3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_p1, a_sq_m1_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_1_1); + bit_met_m1_p1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m1, a_sq_m1_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_1); + bit_met_m1_m1 = _mm256_subs_epi16(xmm1, ch_mag_2_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m3, a_sq_m1_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_3); + bit_met_m1_m3 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m5, a_sq_m1_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_5); + bit_met_m1_m5 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m1_m7, a_sq_m1_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_1_7); + bit_met_m1_m7 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p7, a_sq_m3_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_7); + bit_met_m3_p7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p5, a_sq_m3_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_5); + bit_met_m3_p5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p3, a_sq_m3_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_3); + bit_met_m3_p3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_p1, a_sq_m3_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_3_1); + bit_met_m3_p1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m1, a_sq_m3_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_1); + bit_met_m3_m1 = _mm256_subs_epi16(xmm1, ch_mag_10_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m3, a_sq_m3_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_3); + bit_met_m3_m3 = _mm256_subs_epi16(xmm1, ch_mag_18_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m5, a_sq_m3_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_5); + bit_met_m3_m5 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m3_m7, a_sq_m3_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_3_7); + bit_met_m3_m7 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p7, a_sq_m5_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_7); + bit_met_m5_p7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p5, a_sq_m5_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_5); + bit_met_m5_p5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p3, a_sq_m5_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_3); + bit_met_m5_p3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_p1, a_sq_m5_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_5_1); + bit_met_m5_p1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m1, a_sq_m5_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_1); + bit_met_m5_m1 = _mm256_subs_epi16(xmm1, ch_mag_26_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m3, a_sq_m5_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_3); + bit_met_m5_m3 = _mm256_subs_epi16(xmm1, ch_mag_34_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m5, a_sq_m5_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_5); + bit_met_m5_m5 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m5_m7, a_sq_m5_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_5_7); + bit_met_m5_m7 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p7, a_sq_m7_p7); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_7); + bit_met_m7_p7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p5, a_sq_m7_p5); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_5); + bit_met_m7_p5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p3, a_sq_m7_p3); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_3); + bit_met_m7_p3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_p1, a_sq_m7_p1); + xmm1 = _mm256_subs_epi16(xmm0, y0_m_7_1); + bit_met_m7_p1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m1, a_sq_m7_m1); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_1); + bit_met_m7_m1 = _mm256_subs_epi16(xmm1, ch_mag_50_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m3, a_sq_m7_m3); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_3); + bit_met_m7_m3 = _mm256_subs_epi16(xmm1, ch_mag_58_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m5, a_sq_m7_m5); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_5); + bit_met_m7_m5 = _mm256_subs_epi16(xmm1, ch_mag_74_over_42_with_sigma2); + xmm0 = _mm256_subs_epi16(psi_a_m7_m7, a_sq_m7_m7); + xmm1 = _mm256_subs_epi16(xmm0, y0_p_7_7); + bit_met_m7_m7 = _mm256_subs_epi16(xmm1, ch_mag_98_over_42_with_sigma2); + + // Detection for 1st bit (LTE mapping) + // bit = 1 + xmm0 = _mm256_max_epi16(bit_met_m7_p7, bit_met_m7_p5); + xmm1 = _mm256_max_epi16(bit_met_m7_p3, bit_met_m7_p1); + xmm2 = _mm256_max_epi16(bit_met_m7_m1, bit_met_m7_m3); + xmm3 = _mm256_max_epi16(bit_met_m7_m5, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m5_p5); + xmm1 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m5_p1); + xmm2 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m5_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m5_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m3_p7, bit_met_m3_p5); + xmm1 = _mm256_max_epi16(bit_met_m3_p3, bit_met_m3_p1); + xmm2 = _mm256_max_epi16(bit_met_m3_m1, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m3_m5, bit_met_m3_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m1_p5); + xmm1 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m1_m3); + xmm3 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m1_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + // bit = 0 + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p7_p5); + xmm1 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p7_p1); + xmm2 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p7_m3); + xmm3 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p5_p7, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p5_p3, bit_met_p5_p1); + xmm2 = _mm256_max_epi16(bit_met_p5_m1, bit_met_p5_m3); + xmm3 = _mm256_max_epi16(bit_met_p5_m5, bit_met_p5_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p3_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p3_p1); + xmm2 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p3_m3); + xmm3 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p3_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p1_p7, bit_met_p1_p5); + xmm1 = _mm256_max_epi16(bit_met_p1_p3, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_p1_m1, bit_met_p1_m3); + xmm3 = _mm256_max_epi16(bit_met_p1_m5, bit_met_p1_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y0r = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 2nd bit (LTE mapping) + // bit = 1 + xmm0 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + // bit = 0 + xmm0 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m7_p1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m7_p5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y1r = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 3rd bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_m7_m7, bit_met_m7_m5); + xmm1 = _mm256_max_epi16(bit_met_m7_m3, bit_met_m7_m1); + xmm2 = _mm256_max_epi16(bit_met_m7_p1, bit_met_m7_p3); + xmm3 = _mm256_max_epi16(bit_met_m7_p5, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m5_m5); + xmm1 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m5_m1); + xmm2 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p5_m7, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p5_m3, bit_met_p5_m1); + xmm2 = _mm256_max_epi16(bit_met_p5_p1, bit_met_p5_p3); + xmm3 = _mm256_max_epi16(bit_met_p5_p5, bit_met_p5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p7_m5); + xmm1 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p7_m1); + xmm2 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p7_p3); + xmm3 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_m3_m7, bit_met_m3_m5); + xmm1 = _mm256_max_epi16(bit_met_m3_m3, bit_met_m3_m1); + xmm2 = _mm256_max_epi16(bit_met_m3_p1, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m3_p5, bit_met_m3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m1_m5); + xmm1 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m1_p3); + xmm3 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p1_m7, bit_met_p1_m5); + xmm1 = _mm256_max_epi16(bit_met_p1_m3, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_p1_p1, bit_met_p1_p3); + xmm3 = _mm256_max_epi16(bit_met_p1_p5, bit_met_p1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p3_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p3_m1); + xmm2 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p3_p3); + xmm3 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y2r = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 4th bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m7_p1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y0i = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + + // Detection for 5th bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_m7_m7, bit_met_m7_m5); + xmm1 = _mm256_max_epi16(bit_met_m7_m3, bit_met_m7_m1); + xmm2 = _mm256_max_epi16(bit_met_m7_p1, bit_met_m7_p3); + xmm3 = _mm256_max_epi16(bit_met_m7_p5, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m1_m5); + xmm1 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m1_p3); + xmm3 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p1_m7, bit_met_p1_m5); + xmm1 = _mm256_max_epi16(bit_met_p1_m3, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_p1_p1, bit_met_p1_p3); + xmm3 = _mm256_max_epi16(bit_met_p1_p5, bit_met_p1_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p7_m5); + xmm1 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p7_m1); + xmm2 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p7_p3); + xmm3 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m5_m5); + xmm1 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m5_m1); + xmm2 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_m3_m7, bit_met_m3_m5); + xmm1 = _mm256_max_epi16(bit_met_m3_m3, bit_met_m3_m1); + xmm2 = _mm256_max_epi16(bit_met_m3_p1, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m3_p5, bit_met_m3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p3_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p3_m1); + xmm2 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p3_p3); + xmm3 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p3_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p5_m7, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p5_m3, bit_met_p5_m1); + xmm2 = _mm256_max_epi16(bit_met_p5_p1, bit_met_p5_p3); + xmm3 = _mm256_max_epi16(bit_met_p5_p5, bit_met_p5_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y1i = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // Detection for 6th bit (LTE mapping) + xmm0 = _mm256_max_epi16(bit_met_p7_p7, bit_met_p5_p7); + xmm1 = _mm256_max_epi16(bit_met_p3_p7, bit_met_p1_p7); + xmm2 = _mm256_max_epi16(bit_met_m1_p7, bit_met_m3_p7); + xmm3 = _mm256_max_epi16(bit_met_m5_p7, bit_met_m7_p7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p1, bit_met_p5_p1); + xmm1 = _mm256_max_epi16(bit_met_p3_p1, bit_met_p1_p1); + xmm2 = _mm256_max_epi16(bit_met_m1_p1, bit_met_m3_p1); + xmm3 = _mm256_max_epi16(bit_met_m5_p1, bit_met_m5_p1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m1, bit_met_p5_m1); + xmm1 = _mm256_max_epi16(bit_met_p3_m1, bit_met_p1_m1); + xmm2 = _mm256_max_epi16(bit_met_m1_m1, bit_met_m3_m1); + xmm3 = _mm256_max_epi16(bit_met_m5_m1, bit_met_m7_m1); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m7, bit_met_p5_m7); + xmm1 = _mm256_max_epi16(bit_met_p3_m7, bit_met_p1_m7); + xmm2 = _mm256_max_epi16(bit_met_m1_m7, bit_met_m3_m7); + xmm3 = _mm256_max_epi16(bit_met_m5_m7, bit_met_m7_m7); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm4); + logmax_den_re0 = _mm256_max_epi16(logmax_den_re0, xmm5); + + xmm0 = _mm256_max_epi16(bit_met_p7_m5, bit_met_p5_m5); + xmm1 = _mm256_max_epi16(bit_met_p3_m5, bit_met_p1_m5); + xmm2 = _mm256_max_epi16(bit_met_m1_m5, bit_met_m3_m5); + xmm3 = _mm256_max_epi16(bit_met_m5_m5, bit_met_m7_m5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(xmm4, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_m3, bit_met_p5_m3); + xmm1 = _mm256_max_epi16(bit_met_p3_m3, bit_met_p1_m3); + xmm2 = _mm256_max_epi16(bit_met_m1_m3, bit_met_m3_m3); + xmm3 = _mm256_max_epi16(bit_met_m5_m3, bit_met_m7_m3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p3, bit_met_p5_p3); + xmm1 = _mm256_max_epi16(bit_met_p3_p3, bit_met_p1_p3); + xmm2 = _mm256_max_epi16(bit_met_m1_p3, bit_met_m3_p3); + xmm3 = _mm256_max_epi16(bit_met_m5_p3, bit_met_m7_p3); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + xmm0 = _mm256_max_epi16(bit_met_p7_p5, bit_met_p5_p5); + xmm1 = _mm256_max_epi16(bit_met_p3_p5, bit_met_p1_p5); + xmm2 = _mm256_max_epi16(bit_met_m1_p5, bit_met_m3_p5); + xmm3 = _mm256_max_epi16(bit_met_m5_p5, bit_met_m7_p5); + xmm4 = _mm256_max_epi16(xmm0, xmm1); + xmm5 = _mm256_max_epi16(xmm2, xmm3); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm4); + logmax_num_re0 = _mm256_max_epi16(logmax_num_re0, xmm5); + + y2i = _mm256_subs_epi16(logmax_num_re0, logmax_den_re0); + + // map to output stream, difficult to do in SIMD since we have 6 16bit LLRs + // RE 1 + j = 48*i; + stream0_out[j + 0] = ((short *)&y0r)[0]; + stream0_out[j + 1] = ((short *)&y1r)[0]; + stream0_out[j + 2] = ((short *)&y2r)[0]; + stream0_out[j + 3] = ((short *)&y0i)[0]; + stream0_out[j + 4] = ((short *)&y1i)[0]; + stream0_out[j + 5] = ((short *)&y2i)[0]; + // RE 2 + stream0_out[j + 6] = ((short *)&y0r)[1]; + stream0_out[j + 7] = ((short *)&y1r)[1]; + stream0_out[j + 8] = ((short *)&y2r)[1]; + stream0_out[j + 9] = ((short *)&y0i)[1]; + stream0_out[j + 10] = ((short *)&y1i)[1]; + stream0_out[j + 11] = ((short *)&y2i)[1]; + // RE 3 + stream0_out[j + 12] = ((short *)&y0r)[2]; + stream0_out[j + 13] = ((short *)&y1r)[2]; + stream0_out[j + 14] = ((short *)&y2r)[2]; + stream0_out[j + 15] = ((short *)&y0i)[2]; + stream0_out[j + 16] = ((short *)&y1i)[2]; + stream0_out[j + 17] = ((short *)&y2i)[2]; + // RE 4 + stream0_out[j + 18] = ((short *)&y0r)[3]; + stream0_out[j + 19] = ((short *)&y1r)[3]; + stream0_out[j + 20] = ((short *)&y2r)[3]; + stream0_out[j + 21] = ((short *)&y0i)[3]; + stream0_out[j + 22] = ((short *)&y1i)[3]; + stream0_out[j + 23] = ((short *)&y2i)[3]; + // RE 5 + stream0_out[j + 24] = ((short *)&y0r)[4]; + stream0_out[j + 25] = ((short *)&y1r)[4]; + stream0_out[j + 26] = ((short *)&y2r)[4]; + stream0_out[j + 27] = ((short *)&y0i)[4]; + stream0_out[j + 28] = ((short *)&y1i)[4]; + stream0_out[j + 29] = ((short *)&y2i)[4]; + // RE 6 + stream0_out[j + 30] = ((short *)&y0r)[5]; + stream0_out[j + 31] = ((short *)&y1r)[5]; + stream0_out[j + 32] = ((short *)&y2r)[5]; + stream0_out[j + 33] = ((short *)&y0i)[5]; + stream0_out[j + 34] = ((short *)&y1i)[5]; + stream0_out[j + 35] = ((short *)&y2i)[5]; + // RE 7 + stream0_out[j + 36] = ((short *)&y0r)[6]; + stream0_out[j + 37] = ((short *)&y1r)[6]; + stream0_out[j + 38] = ((short *)&y2r)[6]; + stream0_out[j + 39] = ((short *)&y0i)[6]; + stream0_out[j + 40] = ((short *)&y1i)[6]; + stream0_out[j + 41] = ((short *)&y2i)[6]; + // RE 8 + stream0_out[j + 42] = ((short *)&y0r)[7]; + stream0_out[j + 43] = ((short *)&y1r)[7]; + stream0_out[j + 44] = ((short *)&y2r)[7]; + stream0_out[j + 45] = ((short *)&y0i)[7]; + stream0_out[j + 46] = ((short *)&y1i)[7]; + stream0_out[j + 47] = ((short *)&y2i)[7]; + + // RE 9 + stream0_out[j + 48] = ((short *)&y0r)[8]; + stream0_out[j + 49] = ((short *)&y1r)[8]; + stream0_out[j + 50] = ((short *)&y2r)[8]; + stream0_out[j + 51] = ((short *)&y0i)[8]; + stream0_out[j + 52] = ((short *)&y1i)[8]; + stream0_out[j + 53] = ((short *)&y2i)[8]; + // RE 10 + stream0_out[j + 54] = ((short *)&y0r)[9]; + stream0_out[j + 55] = ((short *)&y1r)[9]; + stream0_out[j + 56] = ((short *)&y2r)[9]; + stream0_out[j + 57] = ((short *)&y0i)[9]; + stream0_out[j + 58] = ((short *)&y1i)[9]; + stream0_out[j + 59] = ((short *)&y2i)[9]; + // RE 11 + stream0_out[j + 60] = ((short *)&y0r)[10]; + stream0_out[j + 61] = ((short *)&y1r)[10]; + stream0_out[j + 62] = ((short *)&y2r)[10]; + stream0_out[j + 63] = ((short *)&y0i)[10]; + stream0_out[j + 64] = ((short *)&y1i)[10]; + stream0_out[j + 65] = ((short *)&y2i)[10]; + // RE 12 + stream0_out[j + 66] = ((short *)&y0r)[11]; + stream0_out[j + 67] = ((short *)&y1r)[11]; + stream0_out[j + 68] = ((short *)&y2r)[11]; + stream0_out[j + 69] = ((short *)&y0i)[11]; + stream0_out[j + 70] = ((short *)&y1i)[11]; + stream0_out[j + 71] = ((short *)&y2i)[11]; + // RE 13 + stream0_out[j + 72] = ((short *)&y0r)[12]; + stream0_out[j + 73] = ((short *)&y1r)[12]; + stream0_out[j + 74] = ((short *)&y2r)[12]; + stream0_out[j + 75] = ((short *)&y0i)[12]; + stream0_out[j + 76] = ((short *)&y1i)[12]; + stream0_out[j + 77] = ((short *)&y2i)[12]; + // RE 14 + stream0_out[j + 78] = ((short *)&y0r)[13]; + stream0_out[j + 79] = ((short *)&y1r)[13]; + stream0_out[j + 80] = ((short *)&y2r)[13]; + stream0_out[j + 81] = ((short *)&y0i)[13]; + stream0_out[j + 82] = ((short *)&y1i)[13]; + stream0_out[j + 83] = ((short *)&y2i)[13]; + // RE 15 + stream0_out[j + 84] = ((short *)&y0r)[14]; + stream0_out[j + 85] = ((short *)&y1r)[14]; + stream0_out[j + 86] = ((short *)&y2r)[14]; + stream0_out[j + 87] = ((short *)&y0i)[14]; + stream0_out[j + 88] = ((short *)&y1i)[14]; + stream0_out[j + 89] = ((short *)&y2i)[14]; + // RE 16 + stream0_out[j + 90] = ((short *)&y0r)[15]; + stream0_out[j + 91] = ((short *)&y1r)[15]; + stream0_out[j + 92] = ((short *)&y2r)[15]; + stream0_out[j + 93] = ((short *)&y0i)[15]; + stream0_out[j + 94] = ((short *)&y1i)[15]; + stream0_out[j + 95] = ((short *)&y2i)[15]; + +#elif defined(__arm__) + +#endif + + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif +} diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 1875ada878a6d5ba6c7842133039051216237b9d..051a3d5d83782d6607dfe52a6e0c5e94f8c51cc3 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -75,12 +75,12 @@ uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, switch (beamforming_mode) { case 7: if (Ncp == NORMAL){ - if ((re!=nushift+offset) && (re!=((nushift+4+offset)%12)) && (re!=((nushift+8+offset)%12))) + if ((re!=nushift+offset) && (re!=((nushift+4+offset)%12)) && (re!=((nushift+8+offset)%12))) return(1); /*else{ printf("(is_no_UEspec_RS):lprime=%d, re=%d, nushift=%d, offset=%d\n",lprime, re,nushift,offset); }*/ - } else { + } else { if ((re!=nushift+offset) && (re!=((nushift+3+offset)%12)) && (re!=((nushift+6+offset)%12)) && (re!=((nushift+9+offset)%12))) return(1); } @@ -158,26 +158,26 @@ uint32_t FOUR[2]={0,4}; uint32_t TWO[2]={0,2}; int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, - int **txdataF, - uint32_t *jj, - uint32_t *jj2, - uint16_t re_offset, - uint32_t symbol_offset, - LTE_DL_eNB_HARQ_t *dlsch0_harq, - LTE_DL_eNB_HARQ_t *dlsch1_harq, - uint8_t pilots, - int16_t amp, - uint8_t precoder_index, - int16_t *qam_table_s0, - int16_t *qam_table_s1, - uint32_t *re_allocated, - uint8_t skip_dc, - uint8_t skip_half, - uint8_t lprime, - uint8_t mprime, - uint8_t Ns, - int *P1_SHIFT, - int *P2_SHIFT) + int **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + uint8_t lprime, + uint8_t mprime, + uint8_t Ns, + int *P1_SHIFT, + int *P2_SHIFT) { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; @@ -190,10 +190,10 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, uint8_t *x0p; if (skip_dc == 0) { - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; - re<12; - re++,x0p+=4,tti_offset++) { - + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<12; + re++,x0p+=4,tti_offset++) { + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -203,11 +203,11 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, } } else { - // 1st half of PRB - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; - re<6; - re++,x0p+=4,tti_offset++) { - + // 1st half of PRB + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<6; + re++,x0p+=4,tti_offset++) { + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -215,11 +215,11 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; } - // 2nd half of PRB - for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; - re<12; - re++,x0p+=4,tti_offset++) { - + // 2nd half of PRB + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; + re<12; + re++,x0p+=4,tti_offset++) { + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -230,33 +230,34 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, } *re_allocated = *re_allocated + 12; *jj=*jj + 48; - + return(0); } int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, - int **txdataF, - uint32_t *jj, - uint32_t *jj2, - uint16_t re_offset, - uint32_t symbol_offset, - LTE_DL_eNB_HARQ_t *dlsch0_harq, - LTE_DL_eNB_HARQ_t *dlsch1_harq, - uint8_t pilots, - int16_t amp, - uint8_t precoder_index, - int16_t *qam_table_s0, - int16_t *qam_table_s1, - uint32_t *re_allocated, - uint8_t skip_dc, - uint8_t skip_half, - uint8_t lprime, - uint8_t mprime, - uint8_t Ns, - int *P1_SHIFT, - int *P2_SHIFT) + int **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + uint8_t lprime, + uint8_t mprime, + uint8_t Ns, + int *P1_SHIFT, + int *P2_SHIFT) { - + + LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; uint8_t *x0 = dlsch0_harq->e; @@ -270,10 +271,10 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, if (skip_dc == 0) { // printf("pilots: P1_SHIFT[0] %d\n",P1_SHIFT[0]); - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; - re<12; - x0p+=4) { - + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<12; + x0p+=4) { + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -286,10 +287,10 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, } } else { - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; - re<6; - x0p+=4) { - + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<6; + x0p+=4) { + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -300,10 +301,10 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, re+=P1_SHIFT[re+1]; } - for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6]; - re<12; - x0p+=4) { - + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6]; + re<12; + x0p+=4) { + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -321,26 +322,26 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, } int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, - int **txdataF, - uint32_t *jj, - uint32_t *jj2, - uint16_t re_offset, - uint32_t symbol_offset, - LTE_DL_eNB_HARQ_t *dlsch0_harq, - LTE_DL_eNB_HARQ_t *dlsch1_harq, - uint8_t pilots, - int16_t amp, - uint8_t precoder_index, - int16_t *qam_table_s0, - int16_t *qam_table_s1, - uint32_t *re_allocated, - uint8_t skip_dc, - uint8_t skip_half, - uint8_t lprime, - uint8_t mprime, - uint8_t Ns, - int *P1_SHIFT, - int *P2_SHIFT) + int **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + uint8_t lprime, + uint8_t mprime, + uint8_t Ns, + int *P1_SHIFT, + int *P2_SHIFT) { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; @@ -357,10 +358,10 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, x0p=&x0[*jj],tti_offset=symbol_offset+re_offset; - /* for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; - re<12; - re+=4,x0p+=24,tti_offset+=4) {*/ - + /* for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<12; + re+=4,x0p+=24,tti_offset+=4) {*/ + qam64_table_offset_re=(x0p[0]<<2)|(x0p[2]<<1)|x0p[4]; qam64_table_offset_im=(x0p[1]<<2)|(x0p[3]<<1)|x0p[5]; ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; @@ -425,10 +426,10 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, // } } else { - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; - re<6; - re++,x0p+=6,tti_offset++) { - + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<6; + re++,x0p+=6,tti_offset++) { + qam64_table_offset_re=FOUR[x0p[0]]; qam64_table_offset_im=FOUR[x0p[1]]; qam64_table_offset_re+=TWO[x0p[2]]; @@ -439,10 +440,10 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; } - for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; - re<12; - re++,x0p+=6,tti_offset++) { - + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; + re<12; + re++,x0p+=6,tti_offset++) { + qam64_table_offset_re=FOUR[x0p[0]]; qam64_table_offset_im=FOUR[x0p[1]]; qam64_table_offset_re+=TWO[x0p[2]]; @@ -456,33 +457,34 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, *re_allocated = *re_allocated + 12; *jj=*jj + 72; - + return(0); } int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, - int **txdataF, - uint32_t *jj, - uint32_t *jj2, - uint16_t re_offset, - uint32_t symbol_offset, - LTE_DL_eNB_HARQ_t *dlsch0_harq, - LTE_DL_eNB_HARQ_t *dlsch1_harq, - uint8_t pilots, - int16_t amp, - uint8_t precoder_index, - int16_t *qam_table_s0, - int16_t *qam_table_s1, - uint32_t *re_allocated, - uint8_t skip_dc, - uint8_t skip_half, - uint8_t lprime, - uint8_t mprime, - uint8_t Ns, - int *P1_SHIFT, - int *P2_SHIFT) + int **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + uint8_t lprime, + uint8_t mprime, + uint8_t Ns, + int *P1_SHIFT, + int *P2_SHIFT) { - + + LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; uint8_t *x0 = dlsch0_harq->e; @@ -496,10 +498,10 @@ int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, if (skip_dc == 0) { // printf("pilots: P1_SHIFT[0] %d\n",P1_SHIFT[0]); - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; - re<12; - x0p+=6) { - + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<12; + x0p+=6) { + qam64_table_offset_re=FOUR[x0p[0]]; qam64_table_offset_im=FOUR[x0p[1]]; qam64_table_offset_re+=TWO[x0p[2]]; @@ -514,10 +516,10 @@ int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, } } else { - for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; - re<6; - x0p+=6) { - + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<6; + x0p+=6) { + qam64_table_offset_re=FOUR[x0p[0]]; qam64_table_offset_im=FOUR[x0p[1]]; qam64_table_offset_re+=TWO[x0p[2]]; @@ -530,10 +532,10 @@ int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, re+=P1_SHIFT[re+1]; } - for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6]; - re<12; - x0p+=6) { - + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6]; + re<12; + x0p+=6) { + qam64_table_offset_re=FOUR[x0p[0]]; qam64_table_offset_im=FOUR[x0p[1]]; qam64_table_offset_re+=TWO[x0p[2]]; @@ -568,31 +570,30 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, uint32_t *re_allocated, uint8_t skip_dc, uint8_t skip_half, - uint8_t lprime, - uint8_t mprime, - uint8_t Ns, - int *P1_SHIFT, - int *P2_SHIFT) + uint8_t lprime, + uint8_t mprime, + uint8_t Ns, + int *P1_SHIFT, + int *P2_SHIFT) { + uint8_t *x0 = NULL; + MIMO_mode_t mimo_mode = -1; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; - MIMO_mode_t mimo_mode = dlsch0_harq->mimo_mode; - - int first_layer0 = dlsch0_harq->first_layer; - int Nlayers0 = dlsch0_harq->Nlayers; - uint8_t mod_order0 = get_Qm(dlsch0_harq->mcs); + int first_layer0 = -1; //= dlsch0_harq->first_layer; + int Nlayers0 = -1; // = dlsch0_harq->Nlayers; + uint8_t mod_order0=0; // = get_Qm(dlsch0_harq->mcs); + uint8_t mod_order1=0; //=2; + uint8_t precoder_index0,precoder_index1; uint8_t *x1=NULL; - uint8_t mod_order1=2; // Fill these in later for TM8-10 // int Nlayers1; // int first_layer1; - int use2ndpilots = (frame_parms->mode1_flag==1)?1:0; uint32_t tti_offset; //,aa; @@ -622,7 +623,6 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, int mprime2 = mprime,ind,ind_dword,ind_qpsk_symb; gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15); - // if (mimo_mode == LARGE_CDD) gain_lin_QPSK>>=1; int32_t qpsk[4]; ((int16_t *)&qpsk[0])[0] = gain_lin_QPSK; @@ -634,19 +634,46 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, ((int16_t *)&qpsk[3])[0] = -gain_lin_QPSK;; ((int16_t *)&qpsk[3])[1] = -gain_lin_QPSK; - if (dlsch1_harq) { + if ((dlsch0_harq != NULL) && (dlsch1_harq != NULL)) { //this is for TM3, TM4 + + x0 = dlsch0_harq->e; + mimo_mode = dlsch0_harq->mimo_mode; + first_layer0 = dlsch0_harq->first_layer; + Nlayers0 = dlsch0_harq->Nlayers; + mod_order0 = get_Qm(dlsch0_harq->mcs); x1 = dlsch1_harq->e; // Fill these in later for TM8-10 // Nlayers1 = dlsch1_harq->Nlayers; // first_layer1 = dlsch1_harq->first_layer; mod_order1 = get_Qm(dlsch1_harq->mcs); + } else if ((dlsch0_harq != NULL) && (dlsch1_harq == NULL)){ //This is for SIS0 TM1, TM6, etc + + x0 = dlsch0_harq->e; + mimo_mode = dlsch0_harq->mimo_mode; + first_layer0 = dlsch0_harq->first_layer; + Nlayers0 = dlsch0_harq->Nlayers; + mod_order0 = get_Qm(dlsch0_harq->mcs); + + } else if ((dlsch0_harq == NULL) && (dlsch1_harq != NULL)){ // This is for TM4 retransmission + + x0 = dlsch1_harq->e; + mimo_mode = dlsch1_harq->mimo_mode; + first_layer0 = dlsch1_harq->first_layer; + Nlayers0 = dlsch1_harq->Nlayers; + mod_order0 = get_Qm(dlsch1_harq->mcs); + } -#ifdef DEBUG_DLSCH_MODULATION - printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], -x0[1+*jj]); -#endif + if (dlsch0_harq != NULL){ + #ifdef DEBUG_DLSCH_MODULATION + printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], x0[1+*jj]); + #endif + } else{ + #ifdef DEBUG_DLSCH_MODULATION + printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], x0[1+*jj]); + #endif + } first_re=0; last_re=12; @@ -658,17 +685,17 @@ x0[1+*jj]); for (re=first_re; re<last_re; re++) { - + // printf("element %d precoder_index for allocation %d\n",re, precoder_index ); if ((skip_dc == 1) && (re==6)) re_off=re_off - frame_parms->ofdm_symbol_size+1; tti_offset = symbol_offset + re_off + re; - // check that RE is not from Cell-specific RS + //check that RE is not from Cell-specific RS if (is_not_pilot(pilots,re,frame_parms->nushift,use2ndpilots)==1) { - // printf("re %d (jj %d)\n",re,*jj); + //printf("re %d (jj %d)\n",re,*jj); if (mimo_mode == SISO) { //SISO mapping @@ -677,16 +704,16 @@ x0[1+*jj]); switch (mod_order0) { case 2: //QPSK - // printf("re %d %d(%d) : %d,%d => ",re,tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); - ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i + + //printf("re %d %d(%d) : %d,%d => ",re,tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i *jj = *jj + 1; - ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} + ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} *jj = *jj + 1; - // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); break; case 4: //16QAM @@ -715,10 +742,8 @@ x0[1+*jj]); *jj=*jj+1; - ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re]; - ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im]; - // ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); - // ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); + ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im]; break; @@ -758,8 +783,8 @@ x0[1+*jj]); *jj=*jj+1; - ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re]; - ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im]; + ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im]; break; @@ -769,6 +794,9 @@ x0[1+*jj]); else if (mimo_mode == ALAMOUTI) { *re_allocated = *re_allocated + 1; + amp = (int16_t)(((int32_t)tmp_amp*ONE_OVER_SQRT2_Q15)>>15); + + switch (mod_order0) { case 2: //QPSK @@ -786,46 +814,41 @@ x0[1+*jj]); ((int16_t*)&tmp_sample2)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj=*jj+1; + //gain_lin_QPSK (=amp/sqrt(2)) is already contains the power offset from rho_a/rho_b, so here we do not need divide by sqrt(2) anymore // normalization for 2 tx antennas - ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); - ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); - ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); - ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0])); + ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1])); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0])); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1])); - break; + break; case 4: //16QAM // Antenna 0 position n - qam16_table_offset_re = 0; qam16_table_offset_im = 0; if (x0[*jj] == 1) qam16_table_offset_re+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im+=2; - *jj=*jj+1; if (x0[*jj] == 1) qam16_table_offset_re+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im+=1; - *jj=*jj+1; //((int16_t *)&txdataF[0][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); //((int16_t *)&txdataF[0][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); - ((int16_t *)&txdataF[0][tti_offset])[0]+=(qam_table_s0[qam16_table_offset_re]*ONE_OVER_SQRT2_Q15)>>15; - ((int16_t *)&txdataF[0][tti_offset])[1]+=(qam_table_s0[qam16_table_offset_im]*ONE_OVER_SQRT2_Q15)>>15; + //gain_lin_QPSK (=amp/sqrt(2)) is already contains the power offset from rho_a/rho_b, so here we do not need divide by sqrt(2) anymore + ((int16_t *)&txdataF[0][tti_offset])[0]+=(qam_table_s0[qam16_table_offset_re]); + ((int16_t *)&txdataF[0][tti_offset])[1]+=(qam_table_s0[qam16_table_offset_im]); // Antenna 1 position n Real part -> -x1* @@ -834,30 +857,27 @@ x0[1+*jj]); if (x0[*jj] == 1) qam16_table_offset_re+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im+=2; - *jj=*jj+1; if (x0[*jj] == 1) qam16_table_offset_re+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im+=1; - *jj=*jj+1; //((int16_t *)&txdataF[1][tti_offset])[0]+=-(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); //((int16_t *)&txdataF[1][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); - ((int16_t *)&txdataF[1][tti_offset])[0]+=-(qam_table_s0[qam16_table_offset_re]*ONE_OVER_SQRT2_Q15)>>15; - ((int16_t *)&txdataF[1][tti_offset])[1]+=(qam_table_s0[qam16_table_offset_im]*ONE_OVER_SQRT2_Q15)>>15; + //qam_table_s0 already contains the power offset from rho_a/rho_b, so here we do not need divide by sqrt(2) anymore + ((int16_t *)&txdataF[1][tti_offset])[0]+=-(qam_table_s0[qam16_table_offset_re]); + ((int16_t *)&txdataF[1][tti_offset])[1]+=(qam_table_s0[qam16_table_offset_im]); + //((int16_t *)&txdataF[1][tti_offset])[0]+=-qam_table_s0[qam16_table_offset_re]; + //((int16_t *)&txdataF[1][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im]; break; @@ -869,141 +889,112 @@ x0[1+*jj]); if (x0[*jj] == 1) qam64_table_offset_re+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=1; - *jj=*jj+1; //((int16_t *)&txdataF[0][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15); //((int16_t *)&txdataF[0][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15); - ((int16_t *)&txdataF[0][tti_offset])[0]+=(qam_table_s0[qam64_table_offset_re]*ONE_OVER_SQRT2_Q15)>>15; - ((int16_t *)&txdataF[0][tti_offset])[1]+=(qam_table_s0[qam64_table_offset_im]*ONE_OVER_SQRT2_Q15)>>15; + //qam_table_s0 already contains the power offset from rho_a/rho_b, so here we do not need divide by sqrt(2) anymore + ((int16_t *)&txdataF[0][tti_offset])[0]+=(qam_table_s0[qam64_table_offset_re]); + ((int16_t *)&txdataF[0][tti_offset])[1]+=(qam_table_s0[qam64_table_offset_im]); // Antenna 1 => -x1* qam64_table_offset_re = 0; qam64_table_offset_im = 0; - if (x0[*jj] == 1) qam64_table_offset_re+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=1; - *jj=*jj+1; //((int16_t *)&txdataF[1][tti_offset])[0]+=-(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15); //((int16_t *)&txdataF[1][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15); - ((int16_t *)&txdataF[1][tti_offset])[0]+=-(qam_table_s0[qam64_table_offset_re]*ONE_OVER_SQRT2_Q15)>>15; - ((int16_t *)&txdataF[1][tti_offset])[1]+=(qam_table_s0[qam64_table_offset_im]*ONE_OVER_SQRT2_Q15)>>15; + //qam_table_s0 already contains the power offset from rho_a/rho_b, so here we do not need divide by sqrt(2) anymore + ((int16_t *)&txdataF[1][tti_offset])[0]+=-(qam_table_s0[qam64_table_offset_re]); + ((int16_t *)&txdataF[1][tti_offset])[1]+=(qam_table_s0[qam64_table_offset_im]); break; } - - // fill in the rest of the ALAMOUTI precoding + // fill in the rest of the ALAMOUTI precoding if (is_not_pilot(pilots,re + 1,frame_parms->nushift,use2ndpilots)==1) { ((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1 ((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1]; ((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0]; //x0* ((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1]; - } else { + } + else { ((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1 ((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1]; ((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0]; //x0* ((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1]; } - } else if (mimo_mode == LARGE_CDD) { + } + else if (mimo_mode == LARGE_CDD) { *re_allocated = *re_allocated + 1; if (frame_parms->nb_antenna_ports_eNB == 2) { switch (mod_order0) { + default: LOG_E(PHY,"Unknown mod_order0 %d\n",mod_order0); xx0_re=xx0_im=0; break; case 2: //QPSK - // printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + //printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); xx0_re = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj = *jj + 1; xx0_im = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj = *jj + 1; - - - - // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + //printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); break; case 4: //16QAM qam16_table_offset_re0 = 0; qam16_table_offset_im0 = 0; - if (x0[*jj] == 1) qam16_table_offset_re0+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im0+=2; - *jj=*jj+1; if (x0[*jj] == 1) qam16_table_offset_re0+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im0+=1; - *jj=*jj+1; xx0_re = qam_table_s0[qam16_table_offset_re0]; @@ -1019,80 +1010,61 @@ x0[1+*jj]); if (x0[*jj] == 1) qam64_table_offset_re0+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im0+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re0+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im0+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re0+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im0+=1; - *jj=*jj+1; xx0_re = qam_table_s0[qam64_table_offset_re0]; xx0_im = qam_table_s0[qam64_table_offset_im0]; - break; } switch (mod_order1) { + default: LOG_E(PHY,"Unknown mod_order1 %d\n",mod_order1); xx1_re=xx1_im=0; break; case 2: //QPSK - // printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + //printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); xx1_re = (x1[*jj2]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj2 = *jj2 + 1; xx1_im = (x1[*jj2]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj2 = *jj2 + 1; - // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + //printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); break; case 4: //16QAM qam16_table_offset_re1 = 0; qam16_table_offset_im1 = 0; - if (x1[*jj2] == 1) qam16_table_offset_re1+=2; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam16_table_offset_im1+=2; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam16_table_offset_re1+=1; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam16_table_offset_im1+=1; - *jj2 = *jj2 + 1; xx1_re = qam_table_s1[qam16_table_offset_re1]; @@ -1107,38 +1079,26 @@ x0[1+*jj]); if (x1[*jj2] == 1) qam64_table_offset_re1+=4; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam64_table_offset_im1+=4; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam64_table_offset_re1+=2; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam64_table_offset_im1+=2; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam64_table_offset_re1+=1; - *jj2 = *jj2 + 1; - if (x1[*jj2] == 1) qam64_table_offset_im1+=1; - *jj2 = *jj2 + 1; xx1_re = qam_table_s1[qam64_table_offset_re1]; xx1_im = qam_table_s1[qam64_table_offset_im1]; - break; } @@ -1161,64 +1121,71 @@ x0[1+*jj]); // s alternates +1/-1 for each RE s = -s; } - } else if ((mimo_mode >= UNIFORM_PRECODING11)&&(mimo_mode <= PUSCH_PRECODING1)) { - // this is for transmission modes 4-6 (1 layer) + } + else if ((mimo_mode >= UNIFORM_PRECODING11)&&(mimo_mode <= PUSCH_PRECODING1)) { + // this is for transmission modes 5-6 (1 layer) *re_allocated = *re_allocated + 1; amp = (int16_t)(((int32_t)tmp_amp*ONE_OVER_SQRT2_Q15)>>15); switch (mod_order0) { - case 2: //QPSK + case 2: ((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj = *jj + 1; ((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; *jj = *jj + 1; - // normalization for 2 tx antennas - ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + //normalization for 2 tx antennas + /*((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); if (frame_parms->nb_antenna_ports_eNB == 2) { layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index); ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + }*/ + + // We remove ONE_OVER_SQRT2_Q15 that was coming from precoder, as now it applied in computation sqrt_rho_a, sqrt_rho_b, same in the receiver in precoder function + + ((int16_t*)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0]; + ((int16_t*)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1]; + + if (frame_parms->nb_antenna_ports_eNB == 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index); + ((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0]; + ((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1]; } break; - case 4: //16QAM + case 4: qam16_table_offset_re = 0; qam16_table_offset_im = 0; if (x0[*jj] == 1) qam16_table_offset_re+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im+=2; - *jj=*jj+1; if (x0[*jj] == 1) qam16_table_offset_re+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam16_table_offset_im+=1; - *jj=*jj+1; - ((int16_t*)&tmp_sample1)[0] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); - ((int16_t*)&tmp_sample1)[1] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); - ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0]; - ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1]; + ((int16_t*)&tmp_sample1)[0] = (int16_t)((qam_table_s0[qam16_table_offset_re])); + ((int16_t*)&tmp_sample1)[1] = (int16_t)((qam_table_s0[qam16_table_offset_im])); - if (frame_parms->nb_antenna_ports_eNB == 2) { + ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0]; + ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1]; + + if (frame_parms->nb_antennas_tx == 2) { layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index); ((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0]; ((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1]; @@ -1226,44 +1193,31 @@ x0[1+*jj]); break; - case 6: //64QAM - + case 6: qam64_table_offset_re = 0; qam64_table_offset_im = 0; - if (x0[*jj] == 1) qam64_table_offset_re+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=4; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=2; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_re+=1; - *jj=*jj+1; - if (x0[*jj] == 1) qam64_table_offset_im+=1; - *jj=*jj+1; - ((int16_t*)&tmp_sample1)[0] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15); - ((int16_t*)&tmp_sample1)[1] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15); + ((int16_t*)&tmp_sample1)[0] = (int16_t)((qam_table_s0[qam64_table_offset_re])); + ((int16_t*)&tmp_sample1)[1] = (int16_t)((qam_table_s0[qam64_table_offset_im])); ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0]; ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1]; @@ -1275,10 +1229,220 @@ x0[1+*jj]); } break; + } + } + else if ((mimo_mode >= DUALSTREAM_UNIFORM_PRECODING1)&&(mimo_mode <= DUALSTREAM_PUSCH_PRECODING)) { + // this is for transmission mode 4 (1 layer) + *re_allocated = *re_allocated + 1; - } + if (precoder_index==0) { + precoder_index0 = 0; //[1 1] + precoder_index1 = 1; //[1 -1] + } + else if (precoder_index==1) { + precoder_index0 = 2; //[1 j] + precoder_index1 = 3; //[1 -j] + } + else { + printf("problem with precoder in TM4\n"); + return(-1); + } + + switch (mod_order0) { + case 2: + + ((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; + *jj = *jj + 1; + ((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; + *jj = *jj + 1; + + //normalization for 2 tx antennas + // We remove ONE_OVER_2_Q15 that was coming from precoder, + //as now it applied in computation sqrt_rho_a, sqrt_rho_b, same in the receiver in precoder function + //ONE_OVER_SQRT2_Q15 remains from it + ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); + + //printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index0); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + } + + break; + + case 4: + + qam16_table_offset_re = 0; + qam16_table_offset_im = 0; + + if (x0[*jj] == 1) + qam16_table_offset_re+=2; + *jj=*jj+1; + if (x0[*jj] == 1) + qam16_table_offset_im+=2; + *jj=*jj+1; + + if (x0[*jj] == 1) + qam16_table_offset_re+=1; + *jj=*jj+1; + if (x0[*jj] == 1) + qam16_table_offset_im+=1; + *jj=*jj+1; + + ((int16_t*)&tmp_sample1)[0] = (int16_t)((qam_table_s0[qam16_table_offset_re])); + ((int16_t*)&tmp_sample1)[1] = (int16_t)((qam_table_s0[qam16_table_offset_im])); + + // We remove ONE_OVER_2_Q15 that was coming from precoder, + //as now it applied in computation sqrt_rho_a, sqrt_rho_b, same in the receiver in precoder function + //ONE_OVER_SQRT2_Q15 remains from it + ((int16_t *)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t *)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index0); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + } + + break; + + case 6: + + qam64_table_offset_re = 0; + qam64_table_offset_im = 0; + + if (x0[*jj] == 1) + qam64_table_offset_re+=4; + *jj=*jj+1; + if (x0[*jj] == 1) + qam64_table_offset_im+=4; + *jj=*jj+1; + if (x0[*jj] == 1) + qam64_table_offset_re+=2; + *jj=*jj+1; + if (x0[*jj] == 1) + qam64_table_offset_im+=2; + *jj=*jj+1; + if (x0[*jj] == 1) + qam64_table_offset_re+=1; + *jj=*jj+1; + if (x0[*jj] == 1) + qam64_table_offset_im+=1; + *jj=*jj+1; + + ((int16_t*)&tmp_sample1)[0] = (int16_t)((qam_table_s0[qam64_table_offset_re])); + ((int16_t*)&tmp_sample1)[1] = (int16_t)((qam_table_s0[qam64_table_offset_im])); + ((int16_t *)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t *)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); + + if (frame_parms->nb_antennas_tx == 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index0); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + } + + break; + } + + if (dlsch1_harq) { + switch (mod_order1) { + + case 2: + + ((int16_t*)&tmp_sample1)[0] = (x1[*jj2]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; + *jj2 = *jj2 + 1; + ((int16_t*)&tmp_sample1)[1] = (x1[*jj2]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; + *jj2 = *jj2 + 1; + + //normalization for 2 tx antennas + ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); + + if (frame_parms->nb_antenna_ports_eNB== 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index1); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + } + + break; + + case 4: + + qam16_table_offset_re = 0; + qam16_table_offset_im = 0; + + if (x1[*jj2] == 1) + qam16_table_offset_re+=2; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam16_table_offset_im+=2; + *jj2=*jj2+1; + + + if (x1[*jj2] == 1) + qam16_table_offset_re+=1; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam16_table_offset_im+=1; + *jj2=*jj2+1; + + ((int16_t*)&tmp_sample1)[0] = (int16_t)((qam_table_s1[qam16_table_offset_re])); + ((int16_t*)&tmp_sample1)[1] = (int16_t)((qam_table_s1[qam16_table_offset_im])); + ((int16_t *)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t *)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index1); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + } + + break; + + case 6: + + qam64_table_offset_re = 0; + qam64_table_offset_im = 0; + if (x1[*jj2] == 1) + qam64_table_offset_re+=4; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam64_table_offset_im+=4; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam64_table_offset_re+=2; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam64_table_offset_im+=2; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam64_table_offset_re+=1; + *jj2=*jj2+1; + if (x1[*jj2] == 1) + qam64_table_offset_im+=1; + *jj2=*jj2+1; + + ((int16_t*)&tmp_sample1)[0] = (int16_t)((qam_table_s1[qam64_table_offset_re])); + ((int16_t*)&tmp_sample1)[1] = (int16_t)((qam_table_s1[qam64_table_offset_im])); + ((int16_t *)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t *)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15); + + if (frame_parms->nb_antenna_ports_eNB == 2) { + layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index1); + ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15); + ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15); + } + + break; + + } + } } + if (mimo_mode == ALAMOUTI) { re++; // adjacent carriers are taken care of by precoding *re_allocated = *re_allocated + 1; @@ -1288,7 +1452,7 @@ x0[1+*jj]); *re_allocated = *re_allocated + 1; } } - + if (mimo_mode == TM7) { *re_allocated = *re_allocated + 1; @@ -1393,7 +1557,7 @@ x0[1+*jj]); } } else if (mimo_mode >= TM8) { //TM8,TM9,TM10 - //uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode) + //uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode) if (is_not_UEspecRS(lprime,re,frame_parms->nushift,frame_parms->Ncp,8)) { switch (mod_order0) { @@ -1444,7 +1608,6 @@ x0[1+*jj]); case 6: //64QAM - qam64_table_offset_re = 0; qam64_table_offset_im = 0; @@ -1492,10 +1655,7 @@ x0[1+*jj]); return(-1); } } - - } - return(0); } @@ -1547,11 +1707,12 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF, tti_offset = symbol_offset + re_off + re; - // printf("re %d (jj %d)\n",re,*jj); + //printf("re %d (jj %d)\n",re,*jj); *re_allocated = *re_allocated + 1; switch (mod_order) { + case 2: //QPSK // printf("%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); @@ -1563,9 +1724,10 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF, *jj = *jj + 1; - // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + //printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); break; + case 4: //16QAM qam16_table_offset_re = 0; @@ -1592,6 +1754,7 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF, *jj=*jj+1; + ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); @@ -1599,7 +1762,6 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF, case 6: //64QAM - qam64_table_offset_re = 0; qam64_table_offset_im = 0; @@ -1644,14 +1806,13 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF, return(0); } -uint8_t get_pmi(uint8_t N_RB_DL,LTE_DL_eNB_HARQ_t *dlsch_harq,uint16_t rb) +uint8_t get_pmi(uint8_t N_RB_DL, MIMO_mode_t mode, uint32_t pmi_alloc,uint16_t rb) { - - + /* MIMO_mode_t mode = dlsch_harq->mimo_mode; uint32_t pmi_alloc = dlsch_harq->pmi_alloc; + */ - // printf("Getting pmi for RB %d => %d\n",rb,(pmi_alloc>>((rb>>2)<<1))&3); switch (N_RB_DL) { case 6: // 1 PRB per subband if (mode <= PUSCH_PRECODING1) @@ -1696,70 +1857,70 @@ inline int check_skip(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL // PBCH if ((subframe_offset==0) && - (rb>((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) { + (rb>((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) { return(1); } if (frame_parms->frame_type == TDD) { // TDD //SSS TDD if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1)) ) { - return(1); - } + return(1); + } //PSS TDD if (((subframe_offset==1) || (subframe_offset==6)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==2) ) { - return(1); + return(1); } } else { //PSS FDD if (((subframe_offset==0)||(subframe_offset==5)) && - (rb>((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==((nsymb>>1)-1)) ) { - return(1); + (rb>((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==((nsymb>>1)-1)) ) { + return(1); } //SSS FDD if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) { - return(1); + return(1); } } } else { // even N_RB_DL //PBCH if ((subframe_offset==0) && - (rb>=((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) + (rb>=((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) return(1); if (frame_parms->frame_type == TDD) { // TDD //SSS if (((subframe_offset==0)|| - (subframe_offset==5)) && - (rb>=((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==nsymb-1) ) { - return(1); + (subframe_offset==5)) && + (rb>=((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==nsymb-1) ) { + return(1); } - + //PSS if (((subframe_offset==1)|| - (subframe_offset==6)) && - (rb>=((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==2) ) { - return(1); + (subframe_offset==6)) && + (rb>=((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==2) ) { + return(1); } } else { // FDD //SSS if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) { - return(1); + return(1); } - + //PSS if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-1)) ) { - return(1); + return(1); } } } @@ -1776,9 +1937,9 @@ inline int check_skiphalf(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_p // PBCH if ((subframe_offset==0) && - (rb==((frame_parms->N_RB_DL>>1)-3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) + (rb==((frame_parms->N_RB_DL>>1)-3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) return(1); else if ((subframe_offset==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) return(2); @@ -1786,26 +1947,26 @@ inline int check_skiphalf(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_p if (frame_parms->frame_type == TDD) { // TDD //SSS TDD if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==(nsymb-1))) - return(1); + return(1); else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1))) - return(2); + return(2); //PSS TDD if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==2)) - return(1); + return(1); else if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==2)) - return(2); + return(2); } else { // FDD //PSS FDD if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==((nsymb>>1)-1))) - return(1); + return(1); else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(((nsymb>>1)-1)))) - return(2); + return(2); //SSS FDD if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && ((l==((nsymb>>1)-2)))) - return(1); + return(1); else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && ((l==(nsymb>>1)-2))) - return(2); + return(2); } } else { // EVEN N_RB_DL @@ -1837,68 +1998,129 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; uint8_t nsymb; - uint8_t harq_pid = dlsch0->current_harq_pid; - LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; - LTE_DL_eNB_HARQ_t *dlsch1_harq; //= dlsch1->harq_processes[harq_pid]; + uint8_t harq_pid = -1; //= dlsch0->current_harq_pid; + LTE_DL_eNB_HARQ_t *dlsch0_harq = NULL; + LTE_DL_eNB_HARQ_t *dlsch1_harq = NULL; //= dlsch1->harq_processes[harq_pid]; uint32_t i,i2,jj,jj2,re_allocated,symbol_offset; uint16_t l,rb,re_offset; uint32_t rb_alloc_ind; - uint32_t *rb_alloc = dlsch0_harq->rb_alloc; + uint32_t *rb_alloc = NULL; //=dlsch0_harq->rb_alloc; + uint8_t pilots=0; - uint8_t skip_dc=0,skip_half=0; - uint8_t mod_order0 = get_Qm(dlsch0_harq->mcs); + uint8_t skip_dc,skip_half; + uint8_t mod_order0 = 0; uint8_t mod_order1 = 0; int16_t amp_rho_a, amp_rho_b; int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8]; int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8]; + int16_t *qam_table_s0=NULL,*qam_table_s1=NULL; +#if 0 + /* TODO: variable to be removed? */ int (*allocate_REs)(PHY_VARS_eNB*, - int **, - uint32_t*, - uint32_t*, - uint16_t, - uint32_t, - LTE_DL_eNB_HARQ_t *, - LTE_DL_eNB_HARQ_t *, - uint8_t, - int16_t, - uint8_t, - int16_t *, - int16_t *, - uint32_t *, - uint8_t, - uint8_t, - uint8_t, - uint8_t, - uint8_t, - int *, - int *); + int **, + uint32_t*, + uint32_t*, + uint16_t, + uint32_t, + LTE_DL_eNB_HARQ_t *, + LTE_DL_eNB_HARQ_t *, + uint8_t, + int16_t, + uint8_t, + int16_t *, + int16_t *, + uint32_t *, + uint8_t, + uint8_t, + uint8_t, + uint8_t, + uint8_t, + int *, + int *); +#endif + int P1_SHIFT[13],P2_SHIFT[13]; int offset,nushiftmod3; - MIMO_mode_t mimo_mode = dlsch0_harq->mimo_mode; + + uint8_t get_pmi_temp; + + MIMO_mode_t mimo_mode = -1; uint8_t mprime=0,Ns; int8_t lprime=-1; int aa=0; + #ifdef DEBUG_DLSCH_MODULATION - uint8_t Nl0 = dlsch0_harq->Nl; + uint8_t Nl0; //= dlsch0_harq->Nl; uint8_t Nl1; #endif - if (dlsch1) { + + if ((dlsch0 != NULL) && (dlsch1 != NULL)){ + + harq_pid = dlsch0->current_harq_pid; + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + mimo_mode = dlsch0_harq->mimo_mode; + mod_order0 = get_Qm(dlsch0_harq->mcs); + rb_alloc = dlsch0_harq->rb_alloc; +#ifdef DEBUG_DLSCH_MODULATION + Nl0 = dlsch0_harq->Nl; +#endif + dlsch1_harq = dlsch1->harq_processes[harq_pid]; mod_order1 = get_Qm(dlsch1_harq->mcs); #ifdef DEBUG_DLSCH_MODULATION Nl1 = dlsch1_harq->Nl; #endif + + }else if ((dlsch0 != NULL) && (dlsch1 == NULL)){ + + harq_pid = dlsch0->current_harq_pid; + dlsch0_harq = dlsch0->harq_processes[harq_pid]; + mimo_mode = dlsch0_harq->mimo_mode; + mod_order0 = get_Qm(dlsch0_harq->mcs); + rb_alloc = dlsch0_harq->rb_alloc; +#ifdef DEBUG_DLSCH_MODULATION + Nl0 = dlsch0_harq->Nl; +#endif + + dlsch1_harq = NULL; + mod_order1 = 0; +#ifdef DEBUG_DLSCH_MODULATION + Nl1 = 0; +#endif + + }else if ((dlsch0 == NULL) && (dlsch1 != NULL)){ + + harq_pid = dlsch1->current_harq_pid; + dlsch1_harq = dlsch1->harq_processes[harq_pid]; + mimo_mode = dlsch1_harq->mimo_mode; + mod_order0 = get_Qm(dlsch1_harq->mcs); + rb_alloc = dlsch1_harq->rb_alloc; +#ifdef DEBUG_DLSCH_MODULATION + Nl0 = dlsch1_harq->Nl; +#endif + + dlsch0_harq = NULL; + mod_order1 = 0; +#ifdef DEBUG_DLSCH_MODULATION + Nl1 = NULL; +#endif + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_IN); nsymb = (frame_parms->Ncp==0) ? 14:12; - amp_rho_a = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_a)>>13); + if (dlsch0 != NULL){ + amp_rho_a = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_a)>>13); //amp=512 in full scale; dlsch0->sqrt_rho_a=8192in Q2.13, 1 in full scale amp_rho_b = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_b)>>13); + } else{ + amp_rho_a = (int16_t)(((int32_t)amp*dlsch1->sqrt_rho_a)>>13); + amp_rho_b = (int16_t)(((int32_t)amp*dlsch1->sqrt_rho_b)>>13); + } if (mod_order0 == 4) for (i=0;i<4; i++) { @@ -1928,20 +2150,22 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, jj2=0; re_allocated=0; - + // printf("num_pdcch_symbols %d, nsymb %d\n",num_pdcch_symbols,nsymb); for (l=num_pdcch_symbols; l<nsymb; l++) { + if (dlsch0 != NULL ) { #ifdef DEBUG_DLSCH_MODULATION - printf("Generating DLSCH (harq_pid %d,mimo %d, pmi_alloc0 %llx, mod0 %d, mod1 %d, rb_alloc[0] %d) in %d\n", - harq_pid, - dlsch0_harq->mimo_mode, - pmi2hex_2Ar1(dlsch0_harq->pmi_alloc), - mod_order0, - mod_order1, - rb_alloc[0], - l); + printf("Generating DLSCH (harq_pid %d,mimo %d, pmi_alloc0 %lx, mod0 %d, mod1 %d, rb_alloc[0] %d) in %d\n", + harq_pid, + dlsch0_harq->mimo_mode, + pmi2hex_2Ar2(dlsch0_harq->pmi_alloc), + mod_order0, + mod_order1, + rb_alloc[0], + len); #endif + } if (frame_parms->Ncp==0) { // normal prefix if ((l==4)||(l==11)) @@ -1987,9 +2211,9 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, for (aa=0;aa<frame_parms->nb_antennas_tx;aa++){ memcpy(phy_vars_eNB->common_vars.beam_weights[0][5][aa],dlsch0->ue_spec_bf_weights[0][aa],frame_parms->ofdm_symbol_size*sizeof(int32_t)); } - + } - + Ns = 2*subframe_offset+(l>=(nsymb>>1)); offset = (pilots==2)?3:0; @@ -1997,23 +2221,23 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, if (pilots>0) { // compute pilot arrays, could be done statically if performance suffers if (frame_parms->mode1_flag == 1) { - // printf("l %d, nushift %d, offset %d\n",l,frame_parms->nushift,offset); - for (i=0,i2=0;i<12;i++) { - if ((i!=(frame_parms->nushift+offset)) && (i!=((frame_parms->nushift+6+offset)%12))) - P1_SHIFT[i2++]=1; - else - P1_SHIFT[i2++]=2; - } - P1_SHIFT[0]--; + // printf("l %d, nushift %d, offset %d\n",l,frame_parms->nushift,offset); + for (i=0,i2=0;i<12;i++) { + if ((i!=(frame_parms->nushift+offset)) && (i!=((frame_parms->nushift+6+offset)%12))) + P1_SHIFT[i2++]=1; + else + P1_SHIFT[i2++]=2; + } + P1_SHIFT[0]--; } else { - for (i=0,i2=0;i<12;i++) { - if ((i!=nushiftmod3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+3) && (i!=nushiftmod3+9)) - P2_SHIFT[i2++]=1; - else - P2_SHIFT[i2++]=2; - } - P2_SHIFT[0]--; + for (i=0,i2=0;i<12;i++) { + if ((i!=nushiftmod3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+3) && (i!=nushiftmod3+9)) + P2_SHIFT[i2++]=1; + else + P2_SHIFT[i2++]=2; + } + P2_SHIFT[0]--; } } P1_SHIFT[12]=1;P2_SHIFT[12]=1; @@ -2021,71 +2245,89 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, re_offset = frame_parms->first_carrier_offset; symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb)); +#if 0 + /* TODO: remove this code? */ allocate_REs = allocate_REs_in_RB; - +#endif + switch (mod_order0) { case 2: qam_table_s0 = NULL; break; case 4: if (pilots) { - qam_table_s0 = qam16_table_b0; - allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? - allocate_REs_in_RB_pilots_16QAM_siso : - allocate_REs_in_RB; + qam_table_s0 = qam16_table_b0; +#if 0 + /* TODO: remove this code? */ + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_pilots_16QAM_siso : + allocate_REs_in_RB; +#endif } else { - qam_table_s0 = qam16_table_a0; - allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? - allocate_REs_in_RB_no_pilots_16QAM_siso : - allocate_REs_in_RB; - + qam_table_s0 = qam16_table_a0; +#if 0 + /* TODO: remove this code? */ + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_no_pilots_16QAM_siso : + allocate_REs_in_RB; +#endif + } break; - + case 6: if (pilots) { - qam_table_s0 = qam64_table_b0; - allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? - allocate_REs_in_RB_pilots_64QAM_siso : - allocate_REs_in_RB; + qam_table_s0 = qam64_table_b0; +#if 0 + /* TODO: remove this code? */ + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_pilots_64QAM_siso : + allocate_REs_in_RB; +#endif } else { - qam_table_s0 = qam64_table_a0; - allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? - allocate_REs_in_RB_no_pilots_64QAM_siso : - allocate_REs_in_RB; + qam_table_s0 = qam64_table_a0; +#if 0 + /* TODO: remove this code? */ + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_no_pilots_64QAM_siso : + allocate_REs_in_RB; +#endif } break; - + } - + switch (mod_order1) { case 2: qam_table_s1 = NULL; +#if 0 + /* TODO: remove this code? */ allocate_REs = allocate_REs_in_RB; +#endif break; case 4: if (pilots) { - qam_table_s1 = qam16_table_b1; + qam_table_s1 = qam16_table_b1; } else { - qam_table_s1 = qam16_table_a1; + qam_table_s1 = qam16_table_a1; } break; case 6: if (pilots) { - qam_table_s1 = qam64_table_b1; + qam_table_s1 = qam64_table_b1; } else { - qam_table_s1 = qam64_table_a1; + qam_table_s1 = qam64_table_a1; } break; - + } //for (aa=0;aa<frame_parms->nb_antennas_tx;aa++) - // memset(&txdataF[aa][symbol_offset],0,frame_parms->ofdm_symbol_size<<2); + //memset(&txdataF[aa][symbol_offset],0,frame_parms->ofdm_symbol_size<<2); //printf("symbol_offset %d,subframe offset %d : pilots %d\n",symbol_offset,subframe_offset,pilots); for (rb=0; rb<frame_parms->N_RB_DL; rb++) { @@ -2101,15 +2343,18 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, rb_alloc_ind = 0; if (check_skip(rb,subframe_offset,frame_parms,l,nsymb)==1) - rb_alloc_ind = 0; + rb_alloc_ind = 0; skip_half = check_skiphalf(rb,subframe_offset,frame_parms,l,nsymb); skip_dc = check_skip_dc(rb,frame_parms); - - if (dlsch0_harq->Nlayers>1) { - printf("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); - return(-1); + + + if (dlsch0) { + if (dlsch0_harq->Nlayers>1) { + msg("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); + return(-1); + } } if (dlsch1) { @@ -2122,40 +2367,52 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, if (rb_alloc_ind > 0) { - // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); - allocate_REs(phy_vars_eNB, - txdataF, - &jj, - &jj2, - re_offset, - symbol_offset, - dlsch0->harq_processes[harq_pid], - (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid], - pilots, - ((pilots) ? amp_rho_b : amp_rho_a), - get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb), - qam_table_s0, - qam_table_s1, - &re_allocated, - skip_dc, - skip_half, - lprime, - mprime, - Ns, - P1_SHIFT, - P2_SHIFT); + // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); + + if (dlsch0 != NULL) { + get_pmi_temp = get_pmi(frame_parms->N_RB_DL, + dlsch0->harq_processes[harq_pid]->mimo_mode, + dlsch0->harq_processes[harq_pid]->pmi_alloc, + rb); + } else + get_pmi_temp = get_pmi(frame_parms->N_RB_DL, + dlsch1->harq_processes[harq_pid]->mimo_mode, + dlsch1->harq_processes[harq_pid]->pmi_alloc, + rb); + + + allocate_REs_in_RB(phy_vars_eNB, + txdataF, + &jj, + &jj2, + re_offset, + symbol_offset, + (dlsch0 == NULL) ? NULL : dlsch0->harq_processes[harq_pid], + (dlsch1 == NULL) ? NULL : dlsch1->harq_processes[harq_pid], + pilots, + ((pilots) ? amp_rho_b : amp_rho_a), + get_pmi_temp, + qam_table_s0, + qam_table_s1, + &re_allocated, + skip_dc, + skip_half, + lprime, + mprime, + Ns, + P1_SHIFT, + P2_SHIFT); if ((mimo_mode == TM7) && (lprime>=0)) mprime +=3+frame_parms->Ncp; - } else { - // printf("Unallocated rb %d/symbol %d, re_offset %d, jj %d\n",rb,l,re_offset,jj); + // printf("Unallocated rb %d/symbol %d, re_offset %d, jj %d\n",rb,l,re_offset,jj); } re_offset+=12; // go to next RB - // check if we crossed the symbol boundary and skip DCs + if (re_offset >= frame_parms->ofdm_symbol_size) { if (skip_dc == 0) //even number of RBs (doesn't straddle DC) re_offset=1; @@ -2163,9 +2420,150 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, re_offset=7; // odd number of RBs } } + } +#ifdef DEBUG_DLSCH_MODULATION + if (dlsch0 != NULL){ + msg("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset)); + }else{ + msg("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch1_harq->nb_rb,dlsch1_harq->rb_alloc,mod_order1,Nl1,2,0,subframe_offset)); } +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT); + + return (re_allocated); +} + + +int dlsch_modulation_SIC(int32_t **sic_buffer, + uint32_t subframe_offset, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch0, + int G) +{ + + uint8_t harq_pid = dlsch0->current_harq_pid; + LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; + uint32_t i,jj,re_allocated=0; + uint8_t mod_order0 = get_Qm(dlsch0_harq->mcs); + uint8_t *x0 = dlsch0_harq->e; + uint8_t qam64_table_offset_re = 0; + uint8_t qam64_table_offset_im = 0; + uint8_t qam16_table_offset_re = 0; + uint8_t qam16_table_offset_im = 0; + int16_t gain_lin_QPSK; + #ifdef DEBUG_DLSCH_MODULATION + uint8_t Nl0 = dlsch0_harq->Nl; + uint8_t Nl1; +#endif + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_IN); + + gain_lin_QPSK = (int16_t)((ONE_OVER_SQRT2_Q15)); + + jj = 0; + i = 0; + while (jj <= G-1) { + + re_allocated = re_allocated + 1; + switch (mod_order0) { + case 2: //QPSK + + ((int16_t*)&sic_buffer[0][i])[0] = (x0[jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i + + jj = jj + 1; + + ((int16_t*)&sic_buffer[0][i])[1] = (x0[jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} + + jj = jj + 1; + + //printf("recon %d,%d\n",((int16_t*)&sic_buffer[0][i])[0],((int16_t*)&sic_buffer[0][i])[1]); + i++; + + break; + + case 4: //16QAM + + qam16_table_offset_re = 0; + qam16_table_offset_im = 0; + + if (x0[jj] == 1) + qam16_table_offset_re+=2; + + jj=jj+1; + + if (x0[jj] == 1) + qam16_table_offset_im+=2; + + jj=jj+1; + + + if (x0[jj] == 1) + qam16_table_offset_re+=1; + + jj=jj+1; + + if (x0[jj] == 1) + qam16_table_offset_im+=1; + + jj=jj+1; + + + ((int16_t *)&sic_buffer[0][i])[0]+=qam16_table[qam16_table_offset_re]; + ((int16_t *)&sic_buffer[0][i])[1]+=qam16_table[qam16_table_offset_im]; + + i++; + + break; + + case 6: + + qam64_table_offset_re = 0; + qam64_table_offset_im = 0; + + if (x0[jj] == 1) + qam64_table_offset_re+=4; + + jj=jj+1; + + if (x0[jj] == 1) + qam64_table_offset_im+=4; + + jj=jj+1; + + if (x0[jj] == 1) + qam64_table_offset_re+=2; + + jj=jj+1; + + if (x0[jj] == 1) + qam64_table_offset_im+=2; + + jj=jj+1; + + if (x0[jj] == 1) + qam64_table_offset_re+=1; + + jj=jj+1; + + if (x0[jj] == 1) + qam64_table_offset_im+=1; + + jj=jj+1; + + + ((int16_t *)&sic_buffer[0][i])[0]+=(qam64_table[qam64_table_offset_re])>>1;//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15); + ((int16_t *)&sic_buffer[0][i])[1]+=(qam64_table[qam64_table_offset_im])>>1;//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15); + + i++; + + break; + } + + } #ifdef DEBUG_DLSCH_MODULATION @@ -2177,6 +2575,7 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, return (re_allocated); } + int mch_modulation(int32_t **txdataF, int16_t amp, uint32_t subframe_offset, @@ -2221,14 +2620,13 @@ int mch_modulation(int32_t **txdataF, if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL - if (rb==(frame_parms->N_RB_DL>>1)) + if (rb==(frame_parms->N_RB_DL>>1)) skip_dc = 1; else skip_dc = 0; } - if (mod_order == 4) qam_table_s = qam16_table_a; else if (mod_order == 6) @@ -2236,7 +2634,7 @@ int mch_modulation(int32_t **txdataF, else qam_table_s = NULL; - // printf("Allocated rb %d, subframe_offset %d,amp %d\n",rb,subframe_offset,amp); + //printf("Allocated rb %d, subframe_offset %d,amp %d\n",rb,subframe_offset,amp); allocate_REs_in_RB_MCH(txdataF, &jj, re_offset, @@ -2252,7 +2650,6 @@ int mch_modulation(int32_t **txdataF, re_offset+=12; // go to next RB - // check if we crossed the symbol boundary and skip DC if (re_offset >= frame_parms->ofdm_symbol_size) { if (skip_dc == 0) //even number of RBs (doesn't straddle DC) @@ -2263,10 +2660,6 @@ int mch_modulation(int32_t **txdataF, } } - - - - #ifdef DEBUG_DLSCH_MODULATION printf("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset,1/*transmission mode*/)); #endif diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c old mode 100755 new mode 100644 index be1bc6b08e27ed3b67bc111ad0c0357f4ad49083..b691717838314336dc126faf7e510d288944f5d2 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -39,6 +39,11 @@ #include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" #include "UTIL/LOG/vcd_signal_dumper.h" + + +const uint8_t lin2alaw_if4p5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; +const uint16_t alaw2lin_if4p5[256] = {60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800, 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752, 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168, 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144, 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592, 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400, 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064, 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968, 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240, 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112, 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496, 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368, 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352, 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840, 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944, 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; + void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = (eNB->CC_id==0) ? eNB->common_vars.txdataF[0] : PHY_vars_eNB_g[0][0]->common_vars.txdataF[0]; @@ -79,19 +84,21 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type gen_IF4p5_dl_header(packet_header, frame, subframe); for (symbol_id=0; symbol_id<nsym; symbol_id++) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); if (eNB->CC_id==1) LOG_I(PHY,"DL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,frame,subframe,symbol_id); for (element_id=0; element_id<db_halflength; element_id++) { i = (uint16_t*) &txdataF[eNB->CC_id][blockoffsetF+element_id]; - data_block[element_id] = ((uint16_t) lin2alaw[*i]) | (lin2alaw[*(i+1)]<<8); + data_block[element_id] = ((uint16_t) lin2alaw_if4p5[*i]) | (lin2alaw_if4p5[*(i+1)]<<8); i = (uint16_t*) &txdataF[eNB->CC_id][slotoffsetF+element_id]; - data_block[element_id+db_halflength] = ((uint16_t) lin2alaw[*i]) | (lin2alaw[*(i+1)]<<8); + data_block[element_id+db_halflength] = ((uint16_t) lin2alaw_if4p5[*i]) | (lin2alaw_if4p5[*(i+1)]<<8); } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); packet_header->frame_status &= ~(0x000f<<26); packet_header->frame_status |= (symbol_id&0x000f)<<26; - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer, @@ -100,7 +107,7 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type IF4p5_PDLFFT)) < 0) { perror("ETHERNET write for IF4p5_PDLFFT\n"); } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } @@ -127,21 +134,23 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type gen_IF4p5_ul_header(packet_header, packet_type, frame, subframe); if (packet_type == IF4p5_PULFFT) { - for (symbol_id=fp->symbols_per_tti-nsym; symbol_id<fp->symbols_per_tti; symbol_id++) { + for (symbol_id=fp->symbols_per_tti-nsym; symbol_id<fp->symbols_per_tti; symbol_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF4_SYMBOL, symbol_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); LOG_D(PHY,"IF4p5_PULFFT: frame %d, subframe %d, symbol %d\n",frame,subframe,symbol_id); for (element_id=0; element_id<db_halflength; element_id++) { i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id]; - data_block[element_id] = ((uint16_t) lin2alaw[*i]) | ((uint16_t)(lin2alaw[*(i+1)]<<8)); + data_block[element_id] = ((uint16_t) lin2alaw_if4p5[*i]) | ((uint16_t)(lin2alaw_if4p5[*(i+1)]<<8)); i = (uint16_t*) &rxdataF[0][slotoffsetF+element_id]; - data_block[element_id+db_halflength] = ((uint16_t) lin2alaw[*i]) | ((uint16_t)(lin2alaw[*(i+1)]<<8)); + data_block[element_id+db_halflength] = ((uint16_t) lin2alaw_if4p5[*i]) | ((uint16_t)(lin2alaw_if4p5[*(i+1)]<<8)); //if (element_id==0) LOG_I(PHY,"send_if4p5: symbol %d rxdata0 = (%d,%d)\n",symbol_id,*i,*(i+1)); } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); packet_header->frame_status &= ~(0x000f<<26); packet_header->frame_status |= (symbol_id&0x000f)<<26; - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer, @@ -150,7 +159,7 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type IF4p5_PULFFT)) < 0) { perror("ETHERNET write for IF4p5_PULFFT\n"); } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } @@ -188,7 +197,7 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type (&rxsigF[0][k]), PRACH_BLOCK_SIZE_BYTES); } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer_prach, @@ -196,7 +205,8 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type 1, IF4p5_PRACH)) < 0) { perror("ETHERNET write for IF4p5_PRACH\n"); - } + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); } else { AssertFatal(1==0, "send_IF4p5 - Unknown packet_type %x", packet_type); } @@ -229,7 +239,8 @@ void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_t IF4p5_header_t *packet_header=NULL; uint16_t *data_block=NULL, *i=NULL; - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, (int64_t*) packet_type, &rx_buffer, @@ -237,7 +248,7 @@ void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_t 0) < 0) { perror("ETHERNET read"); } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); if (eth->flags == ETH_RAW_IF4p5_MODE) { packet_header = (IF4p5_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES); data_block = (uint16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t); @@ -255,45 +266,46 @@ void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_t if (*packet_type == IF4p5_PDLFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF4_SYMBOL, *symbol_number ); LOG_D(PHY,"DL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,*frame,*subframe,*symbol_number); slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 1 ); for (element_id=0; element_id<db_halflength; element_id++) { i = (uint16_t*) &txdataF[0][blockoffsetF+element_id]; - *i = alaw2lin[ (data_block[element_id] & 0xff) ]; - *(i+1) = alaw2lin[ (data_block[element_id]>>8) ]; + *i = alaw2lin_if4p5[ (data_block[element_id] & 0xff) ]; + *(i+1) = alaw2lin_if4p5[ (data_block[element_id]>>8) ]; i = (uint16_t*) &txdataF[0][slotoffsetF+element_id]; - *i = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; - *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ]; + *i = alaw2lin_if4p5[ (data_block[element_id+db_halflength] & 0xff) ]; + *(i+1) = alaw2lin_if4p5[ (data_block[element_id+db_halflength]>>8) ]; } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); } else if (*packet_type == IF4p5_PULFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF4_SYMBOL, *symbol_number ); if (eNB->CC_id==0) LOG_D(PHY,"UL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,*frame,*subframe,*symbol_number); - slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size); blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 1 ); + if (eNB->CC_id==0) LOG_D(PHY,"UL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,*frame,*subframe,*symbol_number); for (element_id=0; element_id<db_halflength; element_id++) { i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id]; - *i = alaw2lin[ (data_block[element_id] & 0xff) ]; - *(i+1) = alaw2lin[ (data_block[element_id]>>8) ]; + *i = alaw2lin_if4p5[ (data_block[element_id] & 0xff) ]; + *(i+1) = alaw2lin_if4p5[ (data_block[element_id]>>8) ]; i = (uint16_t*) &rxdataF[0][slotoffsetF+element_id]; - *i = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; - *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ]; + *i = alaw2lin_if4p5[ (data_block[element_id+db_halflength] & 0xff) ]; + *(i+1) = alaw2lin_if4p5[ (data_block[element_id+db_halflength]>>8) ]; //if (element_id==0) LOG_I(PHY,"recv_if4p5: symbol %d rxdata0 = (%u,%u)\n",*symbol_number,*i,*(i+1)); } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); } else if (*packet_type == IF4p5_PRACH) { - LOG_D(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,*frame,*subframe); - if (eNB->CC_id==1) LOG_I(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,*frame,*subframe); + LOG_D(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d\n",eNB->CC_id,*frame,*subframe); + if (eNB->CC_id==1) LOG_I(PHY,"PRACH_IF4p5: CC_id %d : frame %d, subframe %d\n",eNB->CC_id,*frame,*subframe); // FIX: hard coded prach samples length db_fulllength = PRACH_HARD_CODED_NUM_SAMPLES; diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 5b1c8347053e5bd0e1a1c5709f053bc8f2430eff..b4fc0722d17bd3894b15eaef1f34f8a5e1fef773 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -31,13 +31,22 @@ */ #include "PHY/defs.h" +#include "PHY/TOOLS/alaw_lut.h" -#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "time_utils.h" + +//#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" #include "UTIL/LOG/vcd_signal_dumper.h" //#define DEBUG_DL_MOBIPASS //#define DEBUG_UL_MOBIPASS #define SUBFRAME_SKIP_NUM_MOBIPASS 8 +const uint8_t lin2alaw_if5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; + +const uint16_t alaw2lin_if5[256] = {60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800, 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752, 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168, 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144, 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592, 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400, 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064, 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968, 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240, 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112, 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496, 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368, 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352, 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840, 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944, 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; + +struct timespec start_comp, start_decomp, end_comp, end_decomp; int dummy_cnt = 0; int subframe_skip_extra = 0; int start_flag = 1; @@ -47,55 +56,130 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; int32_t *tx_buffer=NULL; - +#ifdef DEBUG_DL_MOBIPASS int8_t dummy_buffer[fp->samples_per_tti*2]; - uint16_t packet_id=0, i=0; +#endif + void *alaw_buffer = eNB->ifbuffer.tx[subframe&1]; + uint16_t *data_block = NULL; + uint16_t *j = NULL; + uint16_t packet_id=0, i=0, element_id=0; uint32_t spp_eth = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_packet; uint32_t spsf = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - + eth_state_t *eth = (eth_state_t*) (eNB->ifdevice.priv); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); if (packet_type == IF5_RRH_GW_DL) { - - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); - eNB->ifdevice.trx_write_func(&eNB->ifdevice, - (proc_timestamp + packet_id*spp_eth), - (void**)txp, - spp_eth, - fp->nb_antennas_tx, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); + if (eth->compression == ALAW_COMPRESS) { + if (eth->flags == ETH_RAW_MODE) { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); + } else { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES); + } + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + for (i=0; i < fp->nb_antennas_tx; i++) { + for (element_id=0; element_id< spp_eth; element_id++){ + j = (uint16_t*) &eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti+packet_id*spp_eth+element_id]; + data_block[element_id] = ((uint16_t) lin2alaw_if5[*j]) | (lin2alaw_if5[*(j+1)]<<8); + } + } + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] Compress_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + eNB->ifdevice.trx_write_func(&eNB->ifdevice, + (proc_timestamp + packet_id*spp_eth), + (void**)&data_block, + spp_eth, + fp->nb_antennas_tx, + 0); + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); + } + } else if (eth->compression == NO_COMPRESS) { for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] += spp_eth; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + eNB->ifdevice.trx_write_func(&eNB->ifdevice, + (proc_timestamp + packet_id*spp_eth), + (void**)txp, + spp_eth, + fp->nb_antennas_tx, + 0); + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] += spp_eth; + } } - } else if (packet_type == IF5_RRH_GW_UL) { - - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); - eNB->ifdevice.trx_write_func(&eNB->ifdevice, - (proc_timestamp + packet_id*spp_eth), - (void**)rxp, - spp_eth, - fp->nb_antennas_rx, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); + if (eth->compression == ALAW_COMPRESS) { + if (eth->flags == ETH_RAW_MODE) { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); + } else { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES); + } + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + for (i=0; i < fp->nb_antennas_rx; i++) { + for (element_id=0; element_id< spp_eth; element_id++){ + j = (uint16_t*) &eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti+packet_id*spp_eth+element_id]; + data_block[element_id] = ((uint16_t) lin2alaw_if5[*j]) | (lin2alaw_if5[*(j+1)]<<8); + if (packet_id == 0 && element_id == 0) { + //printf("(UL_Tx)Ori: %u(%d, %d); ALAW: %u; SF %u\n",eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti+packet_id*spp_eth+element_id],*j,*(j+1),data_block[element_id],subframe); + } + } + } + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] Compress_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + eNB->ifdevice.trx_write_func(&eNB->ifdevice, + (proc_timestamp + packet_id*spp_eth), + (void**)&data_block, + spp_eth, + fp->nb_antennas_rx, + 0); + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); + } + } else if (eth->compression == NO_COMPRESS) { for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] += spp_eth; - - } + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + eNB->ifdevice.trx_write_func(&eNB->ifdevice, + (proc_timestamp + packet_id*spp_eth), + (void**)rxp, + spp_eth, + fp->nb_antennas_rx, + 0); + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] += spp_eth; + + } + } } else if (packet_type == IF5_MOBIPASS) { uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; @@ -179,70 +263,147 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; - uint16_t packet_id=0, i=0; - int8_t dummy_buffer_rx[fp->samples_per_tti*2]; + uint16_t packet_id=0, i=0, element_id=0; +#ifdef DEBUG_UL_MOBIPASS + //int8_t dummy_buffer_rx[fp->samples_per_tti*2]; uint8_t rxe; +#endif int32_t spp_eth = (int32_t) eNB->ifdevice.openair0_cfg->samples_per_packet; int32_t spsf = (int32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10; - + void *alaw_buffer = eNB->ifbuffer.rx; + uint16_t *data_block = NULL; + uint16_t *j = NULL; openair0_timestamp timestamp[spsf / spp_eth]; + eth_state_t *eth = (eth_state_t*) (eNB->ifdevice.priv); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); if (packet_type == IF5_RRH_GW_DL) { - - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); - eNB->ifdevice.trx_read_func(&eNB->ifdevice, - ×tamp[packet_id], - (void**)txp, - spp_eth, - fp->nb_antennas_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); + if (eth->compression == ALAW_COMPRESS) { + if (eth->flags == ETH_RAW_MODE) { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); + } else { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES); + } + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_decomp); + eNB->ifdevice.trx_read_func(&eNB->ifdevice, + ×tamp[packet_id], + (void**)&data_block, + spp_eth, + fp->nb_antennas_tx); + + clock_gettime( CLOCK_MONOTONIC, &end_decomp); + LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_decomp); + for (i=0; i < fp->nb_antennas_tx; i++) { + for (element_id=0; element_id< spp_eth; element_id++) { + j = (uint16_t*) &eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti+packet_id*spp_eth+element_id]; + *j = alaw2lin_if5[ (data_block[element_id] & 0xff) ]; + *(j+1) = alaw2lin_if5[ (data_block[element_id]>>8) ]; + } + } + clock_gettime( CLOCK_MONOTONIC, &end_decomp); + LOG_D(HW,"[SF %d] Decomperss_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); + } + } else if (eth->compression == NO_COMPRESS) { for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] += spp_eth; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_decomp); + eNB->ifdevice.trx_read_func(&eNB->ifdevice, + ×tamp[packet_id], + (void**)txp, + spp_eth, + fp->nb_antennas_tx); + clock_gettime( CLOCK_MONOTONIC, &end_decomp); + LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] += spp_eth; + } } - *proc_timestamp = timestamp[0]; } else if (packet_type == IF5_RRH_GW_UL) { - - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); - eNB->ifdevice.trx_read_func(&eNB->ifdevice, - ×tamp[packet_id], - (void**)rxp, - spp_eth, - fp->nb_antennas_rx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); + if (eth->compression == ALAW_COMPRESS) { + if (eth->flags == ETH_RAW_MODE) { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); + } else { + data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES); + } + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_decomp); + eNB->ifdevice.trx_read_func(&eNB->ifdevice, + ×tamp[packet_id], + (void**)&data_block, + spp_eth, + fp->nb_antennas_rx); + clock_gettime( CLOCK_MONOTONIC, &end_decomp); + LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_decomp); + for (i=0; i < fp->nb_antennas_rx; i++) { + for (element_id=0; element_id< spp_eth; element_id++) { + j = (uint16_t*) &eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti+packet_id*spp_eth+element_id]; + *j = alaw2lin_if5[ (data_block[element_id] & 0xff) ]; + *(j+1) = alaw2lin_if5[ (data_block[element_id]>>8) ]; + } + } + clock_gettime( CLOCK_MONOTONIC, &end_decomp); + LOG_D(HW,"[SF %d] Decomperss_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); + } + } else if (eth->compression == NO_COMPRESS) { for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] += spp_eth; + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_decomp); + eNB->ifdevice.trx_read_func(&eNB->ifdevice, + ×tamp[packet_id], + (void**)rxp, + spp_eth, + fp->nb_antennas_rx); + clock_gettime( CLOCK_MONOTONIC, &end_decomp); + LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] += spp_eth; + } } - *proc_timestamp = timestamp[0]; } else if (packet_type == IF5_MOBIPASS) { uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength]; +#ifdef DEBUG_UL_MOBIPASS int lower_offset = 0; int upper_offset = 70000; +#endif int subframe_skip = 0; int reset_flag = 0; int32_t *rx_buffer=NULL; __m128i *data_block=NULL, *data_block_head=NULL; __m128i *rxp128; - __m128i r0, r1; + __m128i r0; //rx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); rx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); @@ -363,3 +524,30 @@ if (eNB->CC_id>0) { return; } + +void malloc_IF5_buffer(PHY_VARS_eNB *eNB) { + // Keep the size large enough, 3840 is the number of samples in a packet for 20MHz BW + int i; + eth_state_t *eth = (eth_state_t*) (eNB->ifdevice.priv); + if (eth->compression == ALAW_COMPRESS) { + if (eth->flags == ETH_RAW_MODE) { + for (i=0;i<10;i++) + eNB->ifbuffer.tx[i] = malloc(RAW_PACKET_SIZE_BYTES_ALAW(3840)); + eNB->ifbuffer.rx = malloc(RAW_PACKET_SIZE_BYTES_ALAW(3840)); + } else { + for (i=0;i<10;i++) + eNB->ifbuffer.tx[i] = malloc(UDP_PACKET_SIZE_BYTES_ALAW(3840)); + eNB->ifbuffer.rx = malloc(UDP_PACKET_SIZE_BYTES_ALAW(3840)); + } + } else if (eth->compression == NO_COMPRESS) { + if (eth->flags == ETH_RAW_MODE) { + for (i=0;i<10;i++) + eNB->ifbuffer.tx[i] = malloc(RAW_PACKET_SIZE_BYTES(3840)); + eNB->ifbuffer.rx = malloc(RAW_PACKET_SIZE_BYTES(3840)); + } else { + for (i=0;i<10;i++) + eNB->ifbuffer.tx[i] = malloc(UDP_PACKET_SIZE_BYTES(3840)); + eNB->ifbuffer.rx = malloc(UDP_PACKET_SIZE_BYTES(3840)); + } + } +} diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_tools.h index b6ebe8c841f130a6a0c50f1360a2dbe982c8fe7b..88852de58b88031d6a75b6c42f0dbc1825e0123e 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.h @@ -59,3 +59,5 @@ typedef struct IF5_mobipass_header IF5_mobipass_header_t; void send_IF5(PHY_VARS_eNB*, openair0_timestamp, int, uint8_t*, uint16_t); void recv_IF5(PHY_VARS_eNB*, openair0_timestamp*, int, uint16_t); + +void malloc_IF5_buffer(PHY_VARS_eNB*); diff --git a/openair1/PHY/LTE_TRANSPORT/pcfich.c b/openair1/PHY/LTE_TRANSPORT/pcfich.c index 3b141372f03dd0e12e7077c69903c0033862b9e2..3319cd0f78e163d1cd8854da4fab802358dec10c 100644 --- a/openair1/PHY/LTE_TRANSPORT/pcfich.c +++ b/openair1/PHY/LTE_TRANSPORT/pcfich.c @@ -69,9 +69,9 @@ void generate_pcfich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms) first_reg = pcfich_reg[3]; } - //#ifdef DEBUG_PCFICH + #ifdef DEBUG_PCFICH printf("pcfich_reg : %d,%d,%d,%d\n",pcfich_reg[0],pcfich_reg[1],pcfich_reg[2],pcfich_reg[3]); - //#endif + #endif } void pcfich_scrambling(LTE_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index b46c4167061a35147a9f3d8a94d3b83d89a5f39f..17b9540e4a0ff92792b51240572c002f819129b6 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -135,6 +135,17 @@ unsigned char subframe2_ul_harq(LTE_DL_FRAME_PARMS *frame_parms,unsigned char su break; + case 4: + if ( (subframe == 8) || (subframe == 9) ) { + return(subframe-8); + } else { + LOG_E(PHY,"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d\n", + subframe,frame_parms->tdd_config); + return(0); + } + + break; + } return(0); @@ -307,7 +318,7 @@ void generate_phich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms) Ngroup_PHICH<<=1; } - //#ifdef DEBUG_PHICH + #ifdef DEBUG_PHICH printf("Ngroup_PHICH %d (phich_config_common.phich_resource %d,phich_config_common.phich_duration %s, NidCell %d,Ncp %d, frame_type %d), smallest pcfich REG %d, n0 %d, n1 %d (first PHICH REG %d)\n", ((frame_parms->Ncp == NORMAL)?Ngroup_PHICH:(Ngroup_PHICH>>1)), frame_parms->phich_config_common.phich_resource, @@ -317,7 +328,7 @@ void generate_phich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms) n0, n1, ((frame_parms->Nid_cell))%n0); - //#endif + #endif // This is the algorithm from Section 6.9.3 in 36-211, it works only for normal PHICH duration for now ... @@ -371,9 +382,9 @@ void generate_phich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms) if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3]) frame_parms->phich_reg[mprime][2]++; - //#ifdef DEBUG_PHICH + #ifdef DEBUG_PHICH printf("phich_reg :%d => %d,%d,%d\n",mprime,frame_parms->phich_reg[mprime][0],frame_parms->phich_reg[mprime][1],frame_parms->phich_reg[mprime][2]); - //#endif + #endif } else { // extended PHICH duration frame_parms->phich_reg[mprime<<1][0] = (frame_parms->Nid_cell + mprime)%n0; frame_parms->phich_reg[1+(mprime<<1)][0] = (frame_parms->Nid_cell + mprime)%n0; @@ -1067,7 +1078,7 @@ void rx_phich(PHY_VARS_UE *ue, LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars; + LTE_UE_PDCCH **pdcch_vars = &ue->pdcch_vars[subframe & 0x1][eNB_id]; // uint8_t HI; uint8_t harq_pid = phich_subframe_to_harq_pid(frame_parms,proc->frame_rx,subframe); @@ -1375,11 +1386,7 @@ void rx_phich(PHY_VARS_UE *ue, HI16, nseq_PHICH, ngroup_PHICH); - get_Msg3_alloc_ret(&ue->frame_parms, - subframe, - proc->frame_rx, - &ue->ulsch_Msg3_frame[eNB_id], - &ue->ulsch_Msg3_subframe[eNB_id]); + ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; // ulsch->harq_processes[harq_pid]->Ndi = 0; ulsch->harq_processes[harq_pid]->round++; @@ -1393,13 +1400,14 @@ void rx_phich(PHY_VARS_UE *ue, } } else { //#ifdef DEBUG_PHICH - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received NAK (%d) nseq %d, ngroup %d (Mlimit %d)\n", + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received NAK (%d) nseq %d, ngroup %d round %d (Mlimit %d)\n", ue->Mod_id,harq_pid, proc->frame_rx%1024, subframe, HI16, nseq_PHICH, - ngroup_PHICH,ulsch->harq_processes[harq_pid]->round+1, + ngroup_PHICH, + ulsch->harq_processes[harq_pid]->round, ulsch->Mlimit); //#endif diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c b/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c index 4a9010fca0daa712a9db006f0bbf87594283668f..b4199d9b605e36e2f0ca7fa7002d1b9890e25e11 100644 --- a/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c +++ b/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see <http://www.gnu.org/licenses/>. - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ +/* + * 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.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.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/uespec_pilots.c * \brief Top-level routines for generating DL ue-specific reference signals V12.5 2015-03 diff --git a/openair1/PHY/LTE_TRANSPORT/power_control.c b/openair1/PHY/LTE_TRANSPORT/power_control.c index 4de2b6b775e36a34741126389c1a1463393b2e69..743c16b2f0928b6ff19742443f8aa4766c6f39b4 100644 --- a/openair1/PHY/LTE_TRANSPORT/power_control.c +++ b/openair1/PHY/LTE_TRANSPORT/power_control.c @@ -19,126 +19,132 @@ * contact@openairinterface.org */ -#include "PHY/defs.h" -#include "PHY/impl_defs_lte.h" - -//#define DEBUG_PC 1 - -/* -double ratioPB[2][4]={{ 1.0,4.0/5.0,3.0/5.0,2.0/5.0}, - { 5.0/4.0,1.0,3.0/4.0,1.0/2.0}}; -*/ - -double ratioPB[2][4]= {{ 0.00000, -0.96910, -2.21849, -3.97940}, - { 0.96910, 0.00000, -1.24939, -3.01030} -}; - -double pa_values[8]= {-6.0,-4.77,-3.0,-1.77,0.0,1.0,2.0,3.0}; - -double get_pa_dB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated) -{ - return(pa_values[pdsch_config_dedicated->p_a]); -} - -double computeRhoA_eNB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, - LTE_eNB_DLSCH_t *dlsch_eNB,int dl_power_off) -{ - double rho_a_dB; - double sqrt_rho_a_lin; - - rho_a_dB = pa_values[ pdsch_config_dedicated->p_a]; - - if(!dl_power_off) - rho_a_dB-=10*log10(2); - - sqrt_rho_a_lin= pow(10,(0.05*rho_a_dB)); - - dlsch_eNB->sqrt_rho_a= (short) (sqrt_rho_a_lin*pow(2,13)); - -#ifdef DEBUG_PC - printf("sqrt_rho_a(eNB):%d\n",dlsch_eNB->sqrt_rho_a); -#endif - - return(rho_a_dB); -} - -double computeRhoB_eNB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, - PDSCH_CONFIG_COMMON *pdsch_config_common, - uint8_t n_antenna_port, - LTE_eNB_DLSCH_t *dlsch_eNB, - int dl_power_off) -{ - - double rho_a_dB, rho_b_dB; - double sqrt_rho_b_lin; - - rho_a_dB= computeRhoA_eNB(pdsch_config_dedicated,dlsch_eNB,dl_power_off); - - if(n_antenna_port>1) - rho_b_dB= ratioPB[1][pdsch_config_common->p_b] + rho_a_dB; - else - rho_b_dB= ratioPB[0][pdsch_config_common->p_b] + rho_a_dB; - - sqrt_rho_b_lin= pow(10,(0.05*rho_b_dB)); - - dlsch_eNB->sqrt_rho_b= (short) (sqrt_rho_b_lin*pow(2,13)); - -#ifdef DEBUG_PC - printf("sqrt_rho_b(eNB):%d\n",dlsch_eNB->sqrt_rho_b); -#endif - return(rho_b_dB); -} - - -double computeRhoA_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, - LTE_UE_DLSCH_t *dlsch_ue, - unsigned char dl_power_off) -{ - - double rho_a_dB; - double sqrt_rho_a_lin; - - rho_a_dB = pa_values[ pdsch_config_dedicated->p_a]; - - if(!dl_power_off) - rho_a_dB-=10*log10(2); - - sqrt_rho_a_lin= pow(10,(0.05*rho_a_dB)); - - dlsch_ue->sqrt_rho_a= (short) (sqrt_rho_a_lin*pow(2,13)); - -#ifdef DEBUG_PC - printf("sqrt_rho_a(ue):%d\n",dlsch_ue->sqrt_rho_a); -#endif - - return(rho_a_dB); -} - -double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, - PDSCH_CONFIG_COMMON *pdsch_config_common, - uint8_t n_antenna_port, - LTE_UE_DLSCH_t *dlsch_ue, - unsigned char dl_power_off) -{ - - double rho_a_dB, rho_b_dB; - double sqrt_rho_b_lin; - - rho_a_dB= computeRhoA_UE(pdsch_config_dedicated,dlsch_ue,dl_power_off); - - if(n_antenna_port>1) - rho_b_dB= ratioPB[1][pdsch_config_common->p_b] + rho_a_dB; - else - rho_b_dB= ratioPB[0][pdsch_config_common->p_b] + rho_a_dB; - - sqrt_rho_b_lin= pow(10,(0.05*rho_b_dB)); - - dlsch_ue->sqrt_rho_b= (short) (sqrt_rho_b_lin*pow(2,13)); - -#ifdef DEBUG_PC - printf("sqrt_rho_b(ue):%d\n",dlsch_ue->sqrt_rho_b); -#endif - return(rho_b_dB); -} - - +#include "PHY/defs.h" +#include "PHY/impl_defs_lte.h" + +//#define DEBUG_PC 0 +/* +double ratioPB[2][4]={{ 1.0,4.0/5.0,3.0/5.0,2.0/5.0}, + { 5.0/4.0,1.0,3.0/4.0,1.0/2.0}}; +*/ + +double ratioPB[2][4]={{ 0.00000, -0.96910, -2.21849, -3.97940}, //in db + { 0.96910, 0.00000, -1.24939, -3.01030}}; + +double pa_values[8]={-6.0,-4.77,-3.0,-1.77,0.0,1.0,2.0,3.0}; //reported by higher layers + +double get_pa_dB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated) +{ + if (pdsch_config_dedicated) + return(pa_values[ pdsch_config_dedicated->p_a]); + else + return(0.0); +} + +double computeRhoA_eNB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + LTE_eNB_DLSCH_t *dlsch_eNB, int dl_power_off, uint8_t n_antenna_port){ + double rho_a_dB; + double sqrt_rho_a_lin; + + rho_a_dB = get_pa_dB(pdsch_config_dedicated); + + if(!dl_power_off) //if dl_power_offset is 0, this is for MU-interference, TM5 + rho_a_dB-=10*log10(2); + + if(n_antenna_port==4) // see TS 36.213 Section 5.2 + rho_a_dB=+10*log10(2); + + sqrt_rho_a_lin= pow(10,(0.05*rho_a_dB)); + + dlsch_eNB->sqrt_rho_a= (short) (sqrt_rho_a_lin*pow(2,13)); + +#if DEBUG_PC + printf("eNB: p_a=%d, value=%f, sqrt_rho_a=%d\n",pdsch_config_dedicated->p_a,pa_values[ pdsch_config_dedicated->p_a],dlsch_eNB->sqrt_rho_a); +#endif + + return(rho_a_dB); +} + +double computeRhoB_eNB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + PDSCH_CONFIG_COMMON *pdsch_config_common, + uint8_t n_antenna_port, + LTE_eNB_DLSCH_t *dlsch_eNB, + int dl_power_off) +{ + + double rho_a_dB, rho_b_dB; + double sqrt_rho_b_lin; + + rho_a_dB= computeRhoA_eNB(pdsch_config_dedicated,dlsch_eNB,dl_power_off, n_antenna_port); + + if(n_antenna_port>1) + rho_b_dB= ratioPB[1][pdsch_config_common->p_b] + rho_a_dB; + else + rho_b_dB= ratioPB[0][pdsch_config_common->p_b] + rho_a_dB; + + sqrt_rho_b_lin= pow(10,(0.05*rho_b_dB)); + + dlsch_eNB->sqrt_rho_b= (short) (sqrt_rho_b_lin*pow(2,13)); + +#ifdef DEBUG_PC + printf("eNB: n_ant=%d, p_b=%d -> rho_b/rho_a=%f -> sqrt_rho_b=%d\n",n_antenna_port,pdsch_config_common->p_b,ratioPB[1][pdsch_config_common->p_b],dlsch_eNB->sqrt_rho_b); +#endif + return(rho_b_dB); +} + + +double computeRhoA_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + LTE_UE_DLSCH_t *dlsch_ue, + unsigned char dl_power_off, + uint8_t n_antenna_port + ){ + + double rho_a_dB; + double sqrt_rho_a_lin; + + rho_a_dB = get_pa_dB(pdsch_config_dedicated); + + if(!dl_power_off) + rho_a_dB-=10*log10(2); + //if dl_power_offset is 0, this is for MU-interference, TM5. But in practice UE may assume 16 or 64QAM TM4 as multiuser + + if(n_antenna_port==4) // see TS 36.213 Section 5.2 + rho_a_dB=+10*log10(2); + + sqrt_rho_a_lin= pow(10,(0.05*rho_a_dB)); + + dlsch_ue->sqrt_rho_a= (short) (sqrt_rho_a_lin*pow(2,13)); + +#ifdef DEBUG_PC + printf("UE: p_a=%d, value=%f, dl_power_off=%d, sqrt_rho_a=%d\n",pdsch_config_dedicated->p_a,pa_values[ pdsch_config_dedicated->p_a],dl_power_off,dlsch_ue->sqrt_rho_a); +#endif + + return(rho_a_dB); +} + +double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, + PDSCH_CONFIG_COMMON *pdsch_config_common, + uint8_t n_antenna_port, + LTE_UE_DLSCH_t *dlsch_ue, + unsigned char dl_power_off) +{ + + double rho_a_dB, rho_b_dB; + double sqrt_rho_b_lin; + + rho_a_dB= computeRhoA_UE(pdsch_config_dedicated,dlsch_ue,dl_power_off, n_antenna_port); + + if(n_antenna_port>1) + rho_b_dB= ratioPB[1][pdsch_config_common->p_b] + rho_a_dB; + else + rho_b_dB= ratioPB[0][pdsch_config_common->p_b] + rho_a_dB; + + sqrt_rho_b_lin= pow(10,(0.05*rho_b_dB)); + + dlsch_ue->sqrt_rho_b= (short) (sqrt_rho_b_lin*pow(2,13)); + +#ifdef DEBUG_PC + printf("UE: p_b=%d, n_ant=%d -> ratio=%f -> sqrt_rho_b=%d\n",pdsch_config_common->p_b, n_antenna_port,ratioPB[1][pdsch_config_common->p_b],dlsch_ue->sqrt_rho_b); +#endif + return(rho_b_dB); +} diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 1555162cb49fbcc5f27c355f655c9909d2d4d728..bffcd4b23ace28889a6f7b2e7f8d5aee2d8391c6 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1133,7 +1133,6 @@ void rx_prach(PHY_VARS_eNB *eNB, int fft_size,log2_ifft_size; uint8_t nb_ant_rx = 1; //eNB->frame_parms.nb_antennas_rx; - int en; for (aa=0; aa<nb_ant_rx; aa++) { prach[aa] = (int16_t*)&eNB->common_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset]; diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index c8d4292e8d03c8866f6a053ce1c7a45d37b591ad..9e8fa931ad6e341c2aea2e6da7a62ee5a44d4f51 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -59,7 +59,7 @@ int dump_ue_stats(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,char* buffer, int length return 0; if ((mode == normal_txrx) || (mode == no_L2_connect)) { - len += sprintf(&buffer[len], "[UE_PROC] UE %d, RNTI %x\n",ue->Mod_id, ue->pdcch_vars[0]->crnti); + len += sprintf(&buffer[len], "[UE_PROC] UE %d, RNTI %x\n",ue->Mod_id, ue->pdcch_vars[0][0]->crnti); len += sprintf(&buffer[len],"[UE PROC] RSRP[0] %.2f dBm/RE, RSSI %.2f dBm, RSRQ[0] %.2f dB, N0 %d dBm/RE (NF %.1f dB)\n", 10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB, 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, @@ -107,9 +107,9 @@ int dump_ue_stats(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,char* buffer, int length len += sprintf(&buffer[len], "[UE PROC] Po_PUCCH = %d dBm (Po_NOMINAL_PUCCH %d dBm, g_pucch %d dB)\n", get_PL(ue->Mod_id,ue->CC_id,0)+ ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+ - ue->dlsch[0][0]->g_pucch, + ue->dlsch[0][0][0]->g_pucch, ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - ue->dlsch[0][0]->g_pucch); + ue->dlsch[0][0][0]->g_pucch); } //for (eNB=0;eNB<NUMBER_OF_eNB_MAX;eNB++) { for (eNB=0; eNB<1; eNB++) { @@ -482,24 +482,24 @@ int dump_ue_stats(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,char* buffer, int length len += sprintf(&buffer[len], "[UE PROC] Mode 6 Wideband CQI eNB %d : %d dB\n",eNB,ue->measurements.precoded_cqi_dB[eNB][0]); for (harq_pid=0;harq_pid<8;harq_pid++) { - len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 0 harq_pid %d, mcs %d:",eNB,harq_pid,ue->dlsch[0][0]->harq_processes[harq_pid]->mcs); + len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 0 harq_pid %d, mcs %d:",eNB,harq_pid,ue->dlsch[0][0][0]->harq_processes[harq_pid]->mcs); for (round=0;round<8;round++) len+=sprintf(&buffer[len],"%d/%d ", - ue->dlsch[0][0]->harq_processes[harq_pid]->errors[round], - ue->dlsch[0][0]->harq_processes[harq_pid]->trials[round]); + ue->dlsch[0][0][0]->harq_processes[harq_pid]->errors[round], + ue->dlsch[0][0][0]->harq_processes[harq_pid]->trials[round]); len+=sprintf(&buffer[len],"\n"); } - if (ue->dlsch[0] && ue->dlsch[0][0] && ue->dlsch[0][1]) { - len += sprintf(&buffer[len], "[UE PROC] Saved PMI for DLSCH eNB %d : %jx (%p)\n",eNB,pmi2hex_2Ar1(ue->dlsch[0][0]->pmi_alloc),ue->dlsch[0][0]); + if (ue->dlsch[0][0] && ue->dlsch[0][0][0] && ue->dlsch[0][0][1]) { + len += sprintf(&buffer[len], "[UE PROC] Saved PMI for DLSCH eNB %d : %jx (%p)\n",eNB,pmi2hex_2Ar1(ue->dlsch[0][0][0]->pmi_alloc),ue->dlsch[0][0][0]); - len += sprintf(&buffer[len], "[UE PROC] eNB %d: dl_power_off = %d\n",eNB,ue->dlsch[0][0]->harq_processes[0]->dl_power_off); + len += sprintf(&buffer[len], "[UE PROC] eNB %d: dl_power_off = %d\n",eNB,ue->dlsch[0][0][0]->harq_processes[0]->dl_power_off); for (harq_pid=0;harq_pid<8;harq_pid++) { - len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 1 harq_pid %d, mcs %d:",eNB,harq_pid,ue->dlsch[0][1]->harq_processes[0]->mcs); + len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 1 harq_pid %d, mcs %d:",eNB,harq_pid,ue->dlsch[0][0][1]->harq_processes[0]->mcs); for (round=0;round<8;round++) len+=sprintf(&buffer[len],"%d/%d ", - ue->dlsch[0][1]->harq_processes[harq_pid]->errors[round], - ue->dlsch[0][1]->harq_processes[harq_pid]->trials[round]); + ue->dlsch[0][0][1]->harq_processes[harq_pid]->errors[round], + ue->dlsch[0][0][1]->harq_processes[harq_pid]->trials[round]); len+=sprintf(&buffer[len],"\n"); } } @@ -507,7 +507,7 @@ int dump_ue_stats(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,char* buffer, int length len += sprintf(&buffer[len], "[UE PROC] DLSCH Total %d, Error %d, FER %d\n",ue->dlsch_received[0],ue->dlsch_errors[0],ue->dlsch_fer[0]); len += sprintf(&buffer[len], "[UE PROC] DLSCH (SI) Total %d, Error %d\n",ue->dlsch_SI_received[0],ue->dlsch_SI_errors[0]); len += sprintf(&buffer[len], "[UE PROC] DLSCH (RA) Total %d, Error %d\n",ue->dlsch_ra_received[0],ue->dlsch_ra_errors[0]); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) int i=0; //len += sprintf(&buffer[len], "[UE PROC] MCH Total %d\n", ue->dlsch_mch_received[0]); diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 52c258762badf8673985ddc0109de2dbbf2698ba..2100f07805e58cf2a8542837060aa4431bcc0ae5 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -121,6 +121,18 @@ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, time_stats_t *te_stats, time_stats_t *i_stats); +int32_t dlsch_encoding_SIC(PHY_VARS_UE *ue, + uint8_t *a, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe, + time_stats_t *rm_stats, + time_stats_t *te_stats, + time_stats_t *i_stats); + + + /** \fn dlsch_encoding_2threads(PHY_VARS_eNB *eNB, uint8_t *input_buffer, uint8_t num_pdcch_symbols, @@ -180,7 +192,7 @@ void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB, \brief Fills RB with data \param txdataF pointer to output data (frequency domain signal) \param jj index to output (from CW 1) - \param jj index to output (from CW 2) + \param jj2 index to output (from CW 2) \param re_offset index of the first RE of the RB \param symbol_offset index to the OFDM symbol \param dlsch0_harq Pointer to Transport block 0 HARQ structure @@ -192,7 +204,7 @@ void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB, \param re_allocated pointer to allocation counter \param skip_dc offset for positive RBs \param skip_half indicate that first or second half of RB must be skipped for PBCH/PSS/SSS - \param ue_spec_rs UE specific RS indicator + \param ue_spec_rs UE specific RS indicator \param nb_antennas_tx_phy Physical antenna elements which can be different with antenna port number, especially in beamforming case \param use2ndpilots Set to use the pilots from antenna port 1 for PDSCH \param frame_parms Frame parameter descriptor @@ -281,6 +293,13 @@ int32_t dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch0, LTE_eNB_DLSCH_t *dlsch1); + +int32_t dlsch_modulation_SIC(int32_t **sic_buffer, + uint32_t sub_frame_offset, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch0, + int G); /* \brief This function is the top-level routine for generation of the sub-frame signal (frequency-domain) for MCH. @param txdataF Table of pointers for frequency-domain TX signals @@ -685,6 +704,22 @@ void qam64_qam16(short *stream0_in, short *rho01, int length); +/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/16QAM reception. + @param stream0_in Input from channel compensated (MR combined) stream 0 + @param stream1_in Input from channel compensated (MR combined) stream 1 + @param ch_mag Input from scaled channel magnitude square of h0'*g0 + @param ch_mag_i Input from scaled channel magnitude square of h0'*g1 + @param stream0_out Output from LLR unit for stream0 + @param rho01 Cross-correlation between channels (MR combined) + @param length in complex channel outputs*/ +void qam64_qam16_avx2(short *stream0_in, + short *stream1_in, + short *ch_mag, + short *ch_mag_i, + short *stream0_out, + short *rho01, + int length); + /** \brief This function perform LLR computation for dual-stream (64QAM/16QAM) transmission. @param frame_parms Frame descriptor structure @param rxdataF_comp Compensated channel output @@ -727,6 +762,22 @@ void qam64_qam64(short *stream0_in, short *rho01, int length); +/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/64QAM reception. + @param stream0_in Input from channel compensated (MR combined) stream 0 + @param stream1_in Input from channel compensated (MR combined) stream 1 + @param ch_mag Input from scaled channel magnitude square of h0'*g0 + @param ch_mag_i Input from scaled channel magnitude square of h0'*g1 + @param stream0_out Output from LLR unit for stream0 + @param rho01 Cross-correlation between channels (MR combined) + @param length in complex channel outputs*/ +void qam64_qam64_avx2(int32_t *stream0_in, + int32_t *stream1_in, + int32_t *ch_mag, + int32_t *ch_mag_i, + int16_t *stream0_out, + int32_t *rho01, + int length); + /** \brief This function perform LLR computation for dual-stream (64QAM/64QAM) transmission. @param frame_parms Frame descriptor structure @param rxdataF_comp Compensated channel output @@ -789,6 +840,18 @@ int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, @param beamforming_mode beamforming mode */ +int32_t dlsch_qpsk_llr_SIC(LTE_DL_FRAME_PARMS *frame_parms, + int **rxdataF_comp, + int32_t **sic_buffer, + int **rho_i, + short *dlsch_llr, + uint8_t num_pdcch_symbols, + uint16_t nb_rb, + uint8_t subframe, + uint32_t rb_alloc, + uint16_t mod_order_0, + LTE_UE_DLSCH_t *dlsch0); + void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int16_t *dlsch_llr, @@ -799,7 +862,6 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms, uint16_t pbch_pss_sss_adjust, int16_t **llr128p, uint8_t beamforming_mode); - /** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms @param frame_parms Frame descriptor structure @@ -813,6 +875,34 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms, @param pbch_pss_sss_adjust PBCH/PSS/SSS RE adjustment (in REs) @param beamforming_mode beamforming mode */ +void dlsch_16qam_llr_SIC (LTE_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **sic_buffer, //Q15 + int32_t **rho_i, + int16_t *dlsch_llr, + uint8_t num_pdcch_symbols, + int32_t **dl_ch_mag, + uint16_t nb_rb, + uint8_t subframe, + uint32_t rb_alloc, + uint16_t mod_order_0, + LTE_UE_DLSCH_t *dlsch0); + +void dlsch_64qam_llr_SIC(LTE_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **sic_buffer, //Q15 + int32_t **rho_i, + int16_t *dlsch_llr, + uint8_t num_pdcch_symbols, + int32_t **dl_ch_mag, + int32_t **dl_ch_magb, + uint16_t nb_rb, + uint8_t subframe, + uint32_t rb_alloc, + uint16_t mod_order_0, + LTE_UE_DLSCH_t *dlsch0); + + void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int16_t *dlsch_llr, @@ -825,6 +915,7 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, int16_t **llr_save, uint8_t beamforming_mode); + /** \fn dlsch_siso(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int32_t **rxdataF_comp_i, @@ -922,6 +1013,14 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, uint16_t nb_rb, uint8_t dual_stream_UE); +void dlsch_detection_mrc_TM34(LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDSCH *lte_ue_pdsch_vars, + int harq_pid, + int round, + unsigned char symbol, + unsigned short nb_rb, + unsigned char dual_stream_UE); + /** \fn dlsch_extract_rbs_single(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, @@ -992,7 +1091,8 @@ uint16_t dlsch_extract_rbs_dual(int32_t **rxdataF, uint8_t symbol, uint8_t subframe, uint32_t high_speed_flag, - LTE_DL_FRAME_PARMS *frame_parms); + LTE_DL_FRAME_PARMS *frame_parms, + MIMO_mode_t mimo_mode); /** \fn dlsch_extract_rbs_TM7(int32_t **rxdataF, int32_t **dl_bf_ch_estimates, @@ -1062,6 +1162,15 @@ void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, int **dl_ch_rho_ext, unsigned char output_shift); +void dlsch_dual_stream_correlationTM34(LTE_DL_FRAME_PARMS *frame_parms, + unsigned char symbol, + unsigned short nb_rb, + int **dl_ch_estimates_ext, + int **dl_ch_estimates_ext_i, + int **dl_ch_rho_ext, + unsigned char output_shift0, + unsigned char output_shift1); + void dlsch_channel_compensation_TM56(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, @@ -1077,16 +1186,20 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, unsigned char output_shift, unsigned char dl_power_off); -void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, + +void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_PDSCH *lte_ue_pdsch_vars, PHY_MEASUREMENTS *phy_measurements, int eNB_id, unsigned char symbol, unsigned char mod_order0, unsigned char mod_order1, + int harq_pid, int round, + MIMO_mode_t mimo_mode, unsigned short nb_rb, - unsigned char output_shift); + unsigned char output_shift0, + unsigned char output_shift1); /** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal @@ -1102,11 +1215,16 @@ void dlsch_channel_level(int32_t **dl_ch_estimates_ext, uint8_t pilots_flag, uint16_t nb_rb); -void dlsch_channel_level_TM3(int **dl_ch_estimates_ext, - LTE_DL_FRAME_PARMS *frame_parms, - int *avg, - uint8_t symbol, - unsigned short nb_rb); + +void dlsch_channel_level_TM34(int **dl_ch_estimates_ext, + LTE_DL_FRAME_PARMS *frame_parms, + unsigned char *pmi_ext, + int *avg_0, + int *avg_1, + uint8_t symbol, + unsigned short nb_rb, + MIMO_mode_t mimo_mode); + void dlsch_channel_level_TM56(int32_t **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, @@ -1150,7 +1268,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, LTE_DL_FRAME_PARMS *lte_frame_parms, LTE_UE_DLSCH_t *dlsch, LTE_DL_UE_HARQ_t *harq_process, - uint8_t frame, + uint32_t frame, uint8_t subframe, uint8_t harq_pid, uint8_t is_crnti, @@ -1167,6 +1285,7 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, - RE extraction (pilot, PBCH, synch. signals) - antenna combining (MRC, Alamouti, cycling) - LLR computation + This function supports TM1, 2, 3, 5, and 6. @param phy_vars_ue Pointer to PHY variables @param type Type of PDSCH (SI_PDSCH,RA_PDSCH,PDSCH,PMCH) @param eNB_id eNb index (Nid1) 0,1,2 @@ -1174,7 +1293,7 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, @param subframe Subframe number @param symbol Symbol on which to act (within sub-frame) @param first_symbol_flag set to 1 on first DLSCH symbol - @param dual_stream_UE Flag to indicate dual-stream interference cancellation + @param rx_type. rx_type=RX_IC_single_stream will enable interference cancellation of a second stream when decoding the first stream. In case of TM1, 2, 5, and this can cancel interference from a neighbouring cell given by eNB_id_i. In case of TM5, eNB_id_i should be set to n_connected_eNB to perform multi-user interference cancellation. In case of TM3, eNB_id_i should be set to eNB_id to perform co-channel interference cancellation; this option should be used together with an interference cancellation step [...]. In case of TM3, if rx_type=RX_IC_dual_stream, both streams will be decoded by applying the IC single stream receiver twice. @param i_mod Modulation order of the interfering stream */ int32_t rx_pdsch(PHY_VARS_UE *phy_vars_ue, @@ -1185,13 +1304,11 @@ int32_t rx_pdsch(PHY_VARS_UE *phy_vars_ue, uint8_t subframe, uint8_t symbol, uint8_t first_symbol_flag, - uint8_t dual_stream_UE, + RX_type_t rx_type, uint8_t i_mod, uint8_t harq_pid); -int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, - LTE_UE_PDCCH **lte_ue_pdcch_vars, - LTE_DL_FRAME_PARMS *frame_parms, +int32_t rx_pdcch(PHY_VARS_UE *ue, uint32_t frame, uint8_t subframe, uint8_t eNB_id, @@ -1216,7 +1333,8 @@ int pss_sss_extract(PHY_VARS_UE *phy_vars_ue, @returns 0 on success */ int pss_only_extract(PHY_VARS_UE *phy_vars_ue, - int32_t pss_ext[4][72]); + int32_t pss_ext[4][72], + uint8_t subframe); /*! \brief Extract only SSS resource elements @param phy_vars_ue Pointer to UE variables @@ -1224,7 +1342,8 @@ int pss_only_extract(PHY_VARS_UE *phy_vars_ue, @returns 0 on success */ int sss_only_extract(PHY_VARS_UE *phy_vars_ue, - int32_t sss_ext[4][72]); + int32_t sss_ext[4][72], + uint8_t subframe); /*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix) @param phy_vars_ue Pointer to UE variables @@ -1397,7 +1516,7 @@ uint32_t get_TBS_UL(uint8_t mcs, uint16_t nb_rb); */ uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap); -/* \brief Return prb for a given vrb index +/* \brief Return prb for a given vrb index @param vrb_type VRB type (0=localized,1=distributed) @param rb_alloc_dci rballoc field from DCI */ @@ -1451,9 +1570,11 @@ uint8_t SE2I_TBS(float SE, @param soundingrs_ul_config_dedicated Dynamic configuration from RRC during Connection Establishment @param txdataF pointer to the frequency domain TX signal @returns 0 on success*/ -int generate_srs_rx(LTE_DL_FRAME_PARMS *frame_parms, - SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, - int *txdataF); +int generate_srs(LTE_DL_FRAME_PARMS *frame_parms, + SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, + int *txdataF, + int16_t amp, + uint32_t subframe); int32_t generate_srs_tx_emul(PHY_VARS_UE *phy_vars_ue, uint8_t subframe); @@ -1521,7 +1642,7 @@ uint8_t subframe2harq_pid(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t uint8_t subframe2harq_pid_eNBrx(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); int generate_ue_dlsch_params_from_dci(int frame, - uint8_t subframe, + uint8_t subframe, void *dci_pdu, rnti_t rnti, DCI_format_t dci_format, @@ -1591,10 +1712,6 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, void dump_ulsch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id); - - - - int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci); int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, UE_rxtx_proc_t *proc, char* buffer, int length, runmode_t mode, int input_level_dBm); @@ -1666,6 +1783,7 @@ uint32_t ulsch_encoding(uint8_t *a, PHY_VARS_UE *phy_vars_ue, uint8_t harq_pid, uint8_t eNB_id, + uint8_t subframe_rx, uint8_t tmode, uint8_t control_only_flag, uint8_t Nbundled); @@ -1681,6 +1799,7 @@ uint32_t ulsch_encoding(uint8_t *a, int32_t ulsch_encoding_emul(uint8_t *ulsch_buffer, PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, + uint8_t subframe_rx, uint8_t harq_pid, uint8_t control_only_flag); @@ -1771,9 +1890,19 @@ void print_CQI(void *o,UCI_format_t uci_format,uint8_t eNB_id,int N_RB_DL); void extract_CQI(void *o,UCI_format_t uci_format,LTE_eNB_UE_stats *stats,uint8_t N_RB_DL, uint16_t * crnti, uint8_t * access_mode); void fill_CQI(LTE_UE_ULSCH_t *ulsch,PHY_MEASUREMENTS *meas,uint8_t eNB_id, uint8_t harq_pid,int N_RB_DL, rnti_t rnti, uint8_t trans_mode,double sinr_eff); + void reset_cba_uci(void *o); +/** \brief This routine computes the subband PMI bitmap based on measurements (0,1,2,3 for rank 0 and 0,1 for rank 1) in the format needed for UCI + @param meas pointer to measurements + @param eNB_id eNB_id + @param nb_subbands number of subbands + @returns subband PMI bitmap +*/ uint16_t quantize_subband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,int nb_subbands); + +int32_t pmi_convert_rank1_from_rank2(uint16_t pmi_alloc, int tpmi, int nb_rb); + uint16_t quantize_subband_pmi2(PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t a_id,int nb_subbands); uint64_t pmi2hex_2Ar1(uint32_t pmi); @@ -1784,14 +1913,29 @@ uint64_t cqi2hex(uint32_t cqi); uint16_t computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs); -uint32_t pmi_extend(LTE_DL_FRAME_PARMS *frame_parms,uint8_t wideband_pmi); +/** \brief This routine expands a single (wideband) PMI to subband PMI bitmap similar to the one used in the UCI and in the dlsch_modulation routine + @param frame_parms Pointer to DL frame configuration parameters + @param wideband_pmi (0,1,2,3 for rank 0 and 0,1 for rank 1) + @param rank (0 or 1) + @returns subband PMI bitmap +*/ +uint32_t pmi_extend(LTE_DL_FRAME_PARMS *frame_parms,uint8_t wideband_pmi, uint8_t rank); + +/** \brief This routine extracts a single subband PMI from a bitmap coming from UCI or the pmi_extend function + @param N_RB_DL number of resource blocks + @param mimo_mode + @param pmi_alloc subband PMI bitmap + @param rb resource block for which to extract PMI + @returns subband PMI +*/ +uint8_t get_pmi(uint8_t N_RB_DL,MIMO_mode_t mode, uint32_t pmi_alloc,uint16_t rb); 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 subframe); + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, + const unsigned char subframe); uint16_t get_nCCE(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uint8_t mi); @@ -1849,13 +1993,24 @@ void generate_pucch2x(int32_t **txdataF, PUCCH_FMT_t fmt, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, uint16_t n2_pucch, - uint16_t *payload, + uint8_t *payload, int A, int B2, int16_t amp, uint8_t subframe, uint16_t rnti); +void generate_pucch3x(int32_t **txdataF, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t ncs_cell[20][7], + PUCCH_FMT_t fmt, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint16_t n3_pucch, + uint8_t shortened_format, + uint8_t *payload, + int16_t amp, + uint8_t subframe, + uint16_t rnti); void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, UE_rxtx_proc_t *proc, @@ -1867,15 +2022,15 @@ void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, - PUCCH_FMT_t fmt, - uint8_t UE_id, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - int frame, - uint8_t subframe, - uint8_t pucch1_thres); + PUCCH_FMT_t fmt, + uint8_t UE_id, + uint16_t n1_pucch, + uint16_t n2_pucch, + uint8_t shortened_format, + uint8_t *payload, + int frame, + uint8_t subframe, + uint8_t pucch1_thres); int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, eNB_rxtx_proc_t *proc, @@ -1885,7 +2040,6 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, uint8_t *payload); - /*! \brief Check for PRACH TXop in subframe @param frame_parms Pointer to LTE_DL_FRAME_PARMS @@ -1979,16 +2133,19 @@ double get_pa_dB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated); double computeRhoA_eNB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, LTE_eNB_DLSCH_t *dlsch_eNB, - int dl_power_off); + int dl_power_off, + uint8_t n_antenna_port); double computeRhoB_eNB(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, PDSCH_CONFIG_COMMON *pdsch_config_common, uint8_t n_antenna_port, - LTE_eNB_DLSCH_t *dlsch_eNB,int dl_power_off); + LTE_eNB_DLSCH_t *dlsch_eNB, + int dl_power_off); double computeRhoA_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, LTE_UE_DLSCH_t *dlsch_ue, - uint8_t dl_power_off); + uint8_t dl_power_off, + uint8_t n_antenna_port); double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, PDSCH_CONFIG_COMMON *pdsch_config_common, @@ -2002,7 +2159,7 @@ double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, LTE_UE_DLSCH_t *dlsch_ue); */ -uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); +uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); uint8_t ul_subframe2pdcch_alloc_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n); diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index db671f048c9d066c5413742e0b94ab51d6b37816..8adc693b31c7d668785ea011da34c21ed581ad5b 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -115,6 +115,182 @@ int16_t W3_im[3][6] = {{0 ,0 ,0 }, char pucch_format_string[6][20] = {"format 1\0","format 1a\0","format 1b\0","format 2\0","format 2a\0","format 2b\0"}; +/* PUCCH format3 >> */ +#define D_I 0 +#define D_Q 1 +#define D_IQDATA 2 +#define D_NSLT1SF 2 +#define D_NSYM1SLT 7 +#define D_NSYM1SF 2*7 +#define D_NSC1RB 12 +#define D_NRB1PUCCH 2 +#define D_NPUCCH_SF5 5 +#define D_NPUCCH_SF4 4 + +uint8_t chcod_tbl[128][48] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0}, + {0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1}, + {1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1}, + {0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0}, + {0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0}, + {1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1}, + {1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1}, + {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0}, + {1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1}, + {1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1}, + {0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1}, + {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0}, + {1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0}, + {0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1}, + {0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1}, + {1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0}, + {1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1}, + {0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1}, + {1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0}, + {0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1}, + {0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1}, + {1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0}, + {0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1}, + {0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1}, + {1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0}, + {1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0}, + {0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1}, + {0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1}, + {1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1}, + {0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1}, + {1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0}, + {1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0}, + {0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1}, + {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1}, + {0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0}, + {0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0}, + {1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1}, + {1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1}, + {0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1}, + {1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0}, + {0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1}, + {1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1}, + {0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0}, + {0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1}, + {1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0}, + {1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1}, + {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0}, + {0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0}, + {1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0}, + {0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1}, + {0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1}, + {1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0}, + {1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1}, + {0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0}, + {1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1}, + {1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0}, + {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1}, + {1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1}, + {0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1}, + {1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1}, + {0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0}, + {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1}, + {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0}, + {1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1}, + {1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, + {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0}, + {1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1}, + {1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1}, + {0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1}, + {1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1}, + {0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0}, + {0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0}, + {1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1}, + {1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1}, + {0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1}, + {1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0}, + {1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1}, + {0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, + {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0}, + {0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0}, + {1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0}, + {0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1}, + {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1}, + {1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1} }; + +// W5_TBL +int16_t W5_fmt3_re[5][5] = { {32767, 32767, 32767, 32767, 32767}, + {32767, 10125, -26509, -26509, 10125}, + {32767, -26509, 10125, 10125, -26509}, + {32767, -26509, 10125, 10125, -26509}, + {32767, 10125, -26509, -26509, 10125} }; + +int16_t W5_fmt3_im[5][5] = { {0, 0, 0, 0, 0}, + {0, 31163, 19259, -19259, -31163}, + {0, 19259, -31163, 31163, -19259}, + {0, -19259, 31163, -31163, 19259}, + {0, -31163, -19259, 19259, 31163} }; + +int16_t W4_fmt3[4][4] = { {32767, 32767, 32767, 32767}, + {32767, -32767, 32767, -32767}, + {32767, 32767, -32767, -32767}, + {32767, -32767, -32767, 32767} }; + +// W2 TBL +int16_t W2[2] = {32767, 32767}; + +// e^j*pai*floor (ncs_cell(ns,l)/64)/2 +int16_t RotTBL_re[4] = {32767, 0, -32767, 0}; +int16_t RotTBL_im[4] = {0, 32767, 0, -32767}; + +//np4_tbl, np5_tbl +uint8_t Np5_TBL[5] = {0, 3, 6, 8, 10}; +uint8_t Np4_TBL[4] = {0, 3, 6, 9}; + +// alpha_TBL +int16_t alphaTBL_re[12] = {32767, 28377, 16383, 0, -16383, -28377, -32767, -28377, -16383, 0, 16383, 28377}; +int16_t alphaTBL_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0, -16383, -28377, -32767, -28377, -16383}; + +/* PUCCH format3 << */ + void generate_pucch1x(int32_t **txdataF, LTE_DL_FRAME_PARMS *frame_parms, uint8_t ncs_cell[20][7], @@ -336,6 +512,10 @@ void generate_pucch1x(int32_t **txdataF, case pucch_format2b: AssertFatal(1==0,"should not go here\n"); break; + + case pucch_format3: + fprintf(stderr, "PUCCH format 3 not handled\n"); + abort(); } // switch fmt } else { // These are PUCCH reference symbols @@ -473,7 +653,7 @@ void generate_pucch2x(int32_t **txdataF, PUCCH_FMT_t fmt, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, uint16_t n2_pucch, - uint16_t *payload, + uint8_t *payload, int A, int B2, int16_t amp, @@ -573,7 +753,8 @@ void generate_pucch2x(int32_t **txdataF, n_cs = (ncs_cell[ns][l]+nprime)%12; alpha_ind = 0; - for (n=0; n<12; n++) { + for (n=0; n<12; n++) + { // this is r_uv^alpha(n) ref_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15); ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15); @@ -584,11 +765,25 @@ void generate_pucch2x(int32_t **txdataF, //LOG_I(PHY,"slot %d ofdm# %d ==> d[%d,%d] \n",ns,l,data_ind,n); } else { - ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re>>15); - ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im>>15); - //LOG_I(PHY,"slot %d ofdm# %d ==> dmrs[%d] \n",ns,l,n); - } - alpha_ind = (alpha_ind + n_cs)%12; + if ((l==1) || ( (l==5) && (fmt==pucch_format2) )) + { + ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re>>15); + ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im>>15); + } + // l == 5 && pucch format 2a + else if (fmt==pucch_format2a) + { + ((int16_t *)&zptr[n])[0] = ((int32_t)d[20]*ref_re>>15); + ((int16_t *)&zptr[n])[1] = ((int32_t)d[21]*ref_im>>15); + } + // l == 5 && pucch format 2b + else if (fmt==pucch_format2b) + { + ((int16_t *)&zptr[n])[0] = ((int32_t)d[20]*ref_re>>15); + ((int16_t *)&zptr[n])[1] = ((int32_t)d[21]*ref_im>>15); + } + } // l==1 || l==5 + alpha_ind = (alpha_ind + n_cs)%12; } // n zptr+=12; @@ -645,11 +840,935 @@ void generate_pucch2x(int32_t **txdataF, } } +/* PUCCH format3 >> */ +/* DFT */ +void pucchfmt3_Dft( int16_t *x, int16_t *y ) +{ + int16_t i, k; + int16_t tmp[2]; + int16_t calctmp[D_NSC1RB*2]={0}; + + for (i=0; i<D_NSC1RB; i++) { + for(k=0; k<D_NSC1RB; k++) { + tmp[0] = alphaTBL_re[(12-((i*k)%12))%12]; + tmp[1] = alphaTBL_im[(12-((i*k)%12))%12]; + + calctmp[2*i] += (((int32_t)x[2*k] * tmp[0] - (int32_t)x[2*k+1] * tmp[1])>>15); + calctmp[2*i+1] += (((int32_t)x[2*k+1] * tmp[0] + (int32_t)x[2*k] * tmp[1])>>15); + } + y[2*i] = (int16_t)( (double) calctmp[2*i] / sqrt(D_NSC1RB)); + y[2*i+1] = (int16_t)((double) calctmp[2*i+1] / sqrt(D_NSC1RB)); + } +} + +void generate_pucch3x(int32_t **txdataF, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t ncs_cell[20][7], + PUCCH_FMT_t fmt, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint16_t n3_pucch, + uint8_t shortened_format, + uint8_t *payload, + int16_t amp, + uint8_t subframe, + uint16_t rnti) +{ + + uint32_t u, v; + uint16_t i, j, re_offset; + uint32_t z[12*14], *zptr; + uint32_t y_tilda[12*14]={}, *y_tilda_ptr; + uint8_t ns, nsymb, n_oc, n_oc0, n_oc1; + uint8_t N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6; + uint8_t m, l; + uint8_t n_cs; + int16_t tmp_re, tmp_im, W_re=0, W_im=0; + int32_t *txptr; + uint32_t symbol_offset; + + uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30; + uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; + uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; + uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; + + // variables for channel coding + uint8_t chcod_tbl_idx = 0; + //uint8_t chcod_dt[48] = {}; + + // variables for Scrambling + uint32_t cinit = 0; + uint32_t x1; + uint32_t s,s0,s1; + uint8_t C[48] ={}; + uint8_t scr_dt[48]={}; + + // variables for Modulation + int16_t d_re[24]={}; + int16_t d_im[24]={}; + + // variables for orthogonal sequence selection + uint8_t N_PUCCH_SF0 = 5; + uint8_t N_PUCCH_SF1 = (shortened_format==0)? 5:4; + uint8_t first_slot = 0; + int16_t rot_re=0; + int16_t rot_im=0; + + uint8_t dt_offset; + uint8_t sym_offset; + int16_t y_re[14][12]; //={0}; + int16_t y_im[14][12]; //={0}; + + // DMRS + uint8_t alpha_idx=0; + uint8_t m_alpha_idx=0; + + // TODO + // "SR+ACK/NACK" length is only 7 bits. + // This restriction will be lifted in the future. + // "CQI/PMI/RI+ACK/NACK" will be supported in the future. + + // Channel Coding + for (uint8_t i=0; i<7; i++) { + chcod_tbl_idx += (payload[i]<<i); + } + + // Scrambling + cinit = (subframe + 1) * ((2 * frame_parms->Nid_cell + 1)<<16) + rnti; + s0 = lte_gold_generic(&x1,&cinit,1); + s1 = lte_gold_generic(&x1,&cinit,0); + + for (i=0; i<48; i++) { + s = (i<32)? s0:s1; + j = (i<32)? i:(i-32); + C[i] = ((s>>j)&1); + } + + for (i=0; i<48; i++) { + scr_dt[i] = chcod_tbl[chcod_tbl_idx][i] ^ C[i]; + } + + // Modulation + for (uint8_t i=0; i<48; i+=2){ + if (scr_dt[i]==0 && scr_dt[i+1]==0){ + d_re[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp) >>15); + d_im[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp) >>15); + } else if (scr_dt[i]==0 && scr_dt[i+1]==1) { + d_re[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp) >>15); + d_im[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp) >>15); + } else if (scr_dt[i]==1 && scr_dt[i+1]==0) { + d_re[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp)>>15); + d_im[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp)>>15); + } else if (scr_dt[i]==1 && scr_dt[i+1]==1) { + d_re[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp)>>15); + d_im[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp)>>15); + } else { + //***log Modulation Error! + } + } + + // Calculate Orthogonal Sequence index + n_oc0 = n3_pucch % N_PUCCH_SF1; + if (N_PUCCH_SF1 == 5) { + n_oc1 = (3 * n_oc0) % N_PUCCH_SF1; + } else { + n_oc1 = n_oc0 % N_PUCCH_SF1; + } + + y_tilda_ptr = y_tilda; + zptr = z; + + // loop over 2 slots + for (ns=(subframe<<1), u=u0, v=v0; ns<(2+(subframe<<1)); ns++, u=u1, v=v1) { + first_slot = (ns==(subframe<<1))?1:0; + + //loop over symbols in slot + for (l=0; l<N_UL_symb; l++) { + rot_re = RotTBL_re[(uint8_t) ncs_cell[ns][l]/64] ; + rot_im = RotTBL_im[(uint8_t) ncs_cell[ns][l]/64] ; + + // Comput W_noc(m) (36.211 p. 19) + if ( first_slot == 0 && shortened_format==1) { // second slot and shortened format + n_oc = n_oc1; + + if (l<1) { // data + W_re=W4_fmt3[n_oc][l]; + W_im=0; + } else if (l==1) { // DMRS + W_re=W2[0]; + W_im=0; + } else if (l>=2 && l<5) { // data + W_re=W4_fmt3[n_oc][l-1]; + W_im=0; + } else if (l==5) { // DMRS + W_re=W2[1]; + W_im=0; + } else if ((l>=N_UL_symb-2)) { // data + ; + } else { + //***log W Select Error! + } + } else { + if (first_slot == 1) { // 1st slot or 2nd slot and not shortened + n_oc=n_oc0; + } else { + n_oc=n_oc1; + } + + if (l<1) { // data + W_re=W5_fmt3_re[n_oc][l]; + W_im=W5_fmt3_im[n_oc][l]; + } else if (l==1) { // DMRS + W_re=W2[0]; + W_im=0; + } else if (l>=2 && l<5) { // data + W_re=W5_fmt3_re[n_oc][l-1]; + W_im=W5_fmt3_im[n_oc][l-1]; + } else if (l==5) { // DMRS + W_re=W2[1]; + W_im=0; + } else if ((l>=N_UL_symb-1)) { // data + W_re=W5_fmt3_re[n_oc][l-N_UL_symb+5]; + W_im=W5_fmt3_im[n_oc][l-N_UL_symb+5]; + } else { + //***log W Select Error! + } + } // W Selection end + + // Compute n_cs (36.211 p. 18) + n_cs = ncs_cell[ns][l]; + if (N_PUCCH_SF1 == 5) { + alpha_idx = (n_cs + Np5_TBL[n_oc]) % 12; + } else { + alpha_idx = (n_cs + Np4_TBL[n_oc]) % 12; + } + + // generate pucch data + dt_offset = (first_slot == 1) ? 0:12; + sym_offset = (first_slot == 1) ? 0:7; + + for (i=0; i<12; i++) { + // Calculate yn(i) + tmp_re = (((int32_t) (W_re*rot_re - W_im*rot_im)) >>15); + tmp_im = (((int32_t) (W_re*rot_im + W_im*rot_re)) >>15); + y_re[l+sym_offset][i] = (((int32_t) (tmp_re*d_re[i+dt_offset] - tmp_im*d_im[i+dt_offset]))>>15); + y_im[l+sym_offset][i] = (((int32_t) (tmp_re*d_im[i+dt_offset] + tmp_im*d_re[i+dt_offset]))>>15); + + // cyclic shift + ((int16_t *)&y_tilda_ptr[(l+sym_offset)*12+(i-(ncs_cell[ns][l]%12)+12)%12])[0] = y_re[l+sym_offset][i]; + ((int16_t *)&y_tilda_ptr[(l+sym_offset)*12+(i-(ncs_cell[ns][l]%12)+12)%12])[1] = y_im[l+sym_offset][i]; + + // DMRS + m_alpha_idx = (alpha_idx * i) % 12; + if (l==1 || l==5) { + ((int16_t *)&zptr[(l+sym_offset)*12+i])[0] =(((((int32_t) alphaTBL_re[m_alpha_idx]*ul_ref_sigs[u][v][0][i<<1] - (int32_t) alphaTBL_im[m_alpha_idx] * ul_ref_sigs[u][v][0][1+(i<<1)])>>15) * (int32_t)amp)>>15); + ((int16_t *)&zptr[(l+sym_offset)*12+i])[1] =(((((int32_t) alphaTBL_re[m_alpha_idx]*ul_ref_sigs[u][v][0][1+(i<<1)] + (int32_t) alphaTBL_im[m_alpha_idx] * ul_ref_sigs[u][v][0][i<<1])>>15) * (int32_t)amp)>>15); + } + } + + } // l loop + } // ns + + // DFT for pucch-data + for (l=0; l<14; l++) { + if (l==1 || l==5 || l==8 || l==12) { + ; + } else { + pucchfmt3_Dft((int16_t*)&y_tilda_ptr[l*12],(int16_t*)&zptr[l*12]); + } + } + + + // Mapping + m = n3_pucch / N_PUCCH_SF0; + + if (shortened_format == 1) { + nsymb = (N_UL_symb<<1) - 1; + } else { + nsymb = (N_UL_symb<<1); + } + + for (j=0,l=0; l<(nsymb); l++) { + + if ((l<7) && ((m&1) == 0)) + re_offset = (m*6) + frame_parms->first_carrier_offset; + else if ((l<7) && ((m&1) == 1)) + re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12; + else if ((m&1) == 0) + re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12; + else + re_offset = ((m-1)*6) + frame_parms->first_carrier_offset; + + if (re_offset > frame_parms->ofdm_symbol_size) + re_offset -= (frame_parms->ofdm_symbol_size); + + symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*(l+(subframe*14)); + txptr = &txdataF[0][symbol_offset]; + + for (i=0; i<12; i++,j++) { + txptr[re_offset++] = z[j]; + + if (re_offset==frame_parms->ofdm_symbol_size) + re_offset = 0; + +#ifdef DEBUG_PUCCH_TX + msg("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]); +#endif + } + } + +} + +/* PUCCH format3 << */ + //#define Amax 13 //void init_pucch2x_rx() {}; +/* PUCCH format3 >> */ +/* SubCarrier Demap */ +uint16_t pucchfmt3_subCarrierDeMapping( PHY_VARS_eNB *eNB, + int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2], + uint16_t n3_pucch ) +{ + LTE_eNB_COMMON *eNB_common_vars = &eNB->common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + int16_t *rxptr; + uint8_t N_UL_symb = D_NSYM1SLT; // only Normal CP format + uint16_t m; // Mapping to physical resource blocks(m) + uint32_t aa; + uint16_t k, l; + uint32_t symbol_offset; + uint16_t carrier_offset; + + + m = n3_pucch / D_NPUCCH_SF5; + + // Do detection + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + + for (l=0; l<D_NSYM1SF; l++) { + + if ((l<N_UL_symb) && ((m&1) == 0)) + carrier_offset = (m*6) + frame_parms->first_carrier_offset; + else if ((l<N_UL_symb) && ((m&1) == 1)) + carrier_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12; + else if ((m&1) == 0) + carrier_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12; + else + carrier_offset = (((m-1)*6) + frame_parms->first_carrier_offset); + + if (carrier_offset > frame_parms->ofdm_symbol_size) + carrier_offset -= (frame_parms->ofdm_symbol_size); + + symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*l; + rxptr = (int16_t *)&eNB_common_vars->rxdataF[0][aa][symbol_offset]; + + for (k=0; k<12; k++,carrier_offset++) { + SubCarrierDeMapData[aa][l][k][0] = (int16_t)rxptr[carrier_offset<<1]; // DeMapping Data I + SubCarrierDeMapData[aa][l][k][1] = (int16_t)rxptr[1+(carrier_offset<<1)]; // DeMapping Date Q + + if (carrier_offset==frame_parms->ofdm_symbol_size) + carrier_offset = 0; + + #ifdef DEBUG_PUCCH_RX + LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d,%d) : (%d,%d)\n",subframe,l,k,carrier_offset,m, + SubCarrierDeMapData[aa][l][k][0],SubCarrierDeMapData[aa][l][k][1]); + #endif + } + } + } + return 0; +} + +/* cyclic shift hopping remove */ +uint16_t pucchfmt3_Baseseq_csh_remove( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2], + int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2], + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t subframe, + uint8_t ncs_cell[20][7] ) +{ + //int16_t calctmp_baSeq[2]; + int16_t calctmp_beta[2]; + int16_t calctmp_alphak[2]; + int16_t calctmp_SCDeMapData_alphak[2]; + int32_t n_cell_cs_div64; + int32_t n_cell_cs_modNSC_RB; + + //int32_t NSlot1subframe = D_NSLT1SF; + int32_t NSym1slot = D_NSYM1SLT; // Symbol per 1slot + int32_t NSym1subframe = D_NSYM1SF; // Symbol per 1subframe + int32_t aa, symNo, slotNo, sym, k; + + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { // Antenna + for (symNo=0; symNo<NSym1subframe; symNo++) { // Symbol + slotNo = symNo / NSym1slot; + sym = symNo % NSym1slot; + + n_cell_cs_div64 = (int32_t)(ncs_cell[2*subframe+slotNo][sym]/64.0); + n_cell_cs_modNSC_RB = ncs_cell[2*subframe+slotNo][sym] % 12; + + // for canceling e^(j*PI|_n_cs^cell(ns,l)/64_|/2). + calctmp_beta[0] = RotTBL_re[(n_cell_cs_div64)&0x3]; + calctmp_beta[1] = RotTBL_im[(n_cell_cs_div64)&0x3]; + + for (k=0; k<12; k++) { // Sub Carrier + + // for canceling being cyclically shifted"(i+n_cs^cell(ns,l))". + // e^((j*2PI(n_cs^cell(ns,l) mod N_SC)/N_SC)*k). + calctmp_alphak[0] = alphaTBL_re[((n_cell_cs_modNSC_RB)*k)%12]; + calctmp_alphak[1] = alphaTBL_im[((n_cell_cs_modNSC_RB)*k)%12]; + + // e^(-alphar*k)*r_l,m,n,k + calctmp_SCDeMapData_alphak[0] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][0] * calctmp_alphak[0] + (int32_t)SubCarrierDeMapData[aa][symNo][k][1] * calctmp_alphak[1])>>15); + calctmp_SCDeMapData_alphak[1] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][1] * calctmp_alphak[0] - (int32_t)SubCarrierDeMapData[aa][symNo][k][0] * calctmp_alphak[1])>>15); + + // (e^(-alphar*k)*r_l,m,n,k) * e^(-beta) + CshData_fmt3[aa][symNo][k][0] = (((int32_t)calctmp_SCDeMapData_alphak[0] * calctmp_beta[0] + (int32_t)calctmp_SCDeMapData_alphak[1] * calctmp_beta[1])>>15); + CshData_fmt3[aa][symNo][k][1] = (((int32_t)calctmp_SCDeMapData_alphak[1] * calctmp_beta[0] - (int32_t)calctmp_SCDeMapData_alphak[0] * calctmp_beta[1])>>15); + } + } + } + return 0; +} + +#define MAXROW_TBL_SF5_OS_IDX (5) // Orthogonal sequence index +const int16_t TBL_3_SF5_GEN_N_DASH_NS[MAXROW_TBL_SF5_OS_IDX] = {0,3,6,8,10}; + +#define MAXROW_TBL_SF4_OS_IDX (4) // Orthogonal sequence index +const int16_t TBL_3_SF4_GEN_N_DASH_NS[MAXROW_TBL_SF4_OS_IDX] = {0,3,6,9}; + +/* Channel estimation */ +uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2], + double delta_theta[NB_ANTENNAS_RX][12], + int16_t ChestValue[NB_ANTENNAS_RX][2][12][2], + int16_t *Interpw, + uint8_t subframe, + uint8_t shortened_format, + LTE_DL_FRAME_PARMS *frame_parms, + uint16_t n3_pucch, + uint16_t n3_pucch_array[NUMBER_OF_UE_MAX], + uint8_t ncs_cell[20][7] ) +{ + uint32_t aa, symNo, k, slotNo, sym, i, j; + int16_t np, np_n, ip_ind; + //int16_t npucch_sf; + int16_t calctmp[2]; + int16_t BsCshData[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; + //int16_t delta_theta_calctmp[NB_ANTENNAS_RX][4][D_NSC1RB][2], delta_theta_comp[NB_ANTENNAS_RX][D_NSC1RB][2]; + int16_t delta_theta_comp[NB_ANTENNAS_RX][D_NSC1RB][2]; + int16_t CsData_allavg[NB_ANTENNAS_RX][14][2]; + int16_t CsData_temp[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; + int32_t IP_CsData_allsfavg[NB_ANTENNAS_RX][14][4][2]; + int32_t IP_allavg[D_NPUCCH_SF5]; + //int16_t temp_ch[2]; + int16_t m[NUMBER_OF_UE_MAX], m_self, same_m_number; + uint16_t n3_pucch_sameRB[NUMBER_OF_UE_MAX]; + int16_t n_oc0[NUMBER_OF_UE_MAX]; + int16_t n_oc1[NUMBER_OF_UE_MAX]; + int16_t np_n_array[2][NUMBER_OF_UE_MAX]; //Cyclic shift + uint8_t N_PUCCH_SF0 = 5; + uint8_t N_PUCCH_SF1 = (shortened_format==0)? 5:4; + + uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30; + uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; + uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; + uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; + + uint32_t u=u0; + uint32_t v=v0; + + //double d_theta[32]={0.0}; + //int32_t temp_theta[32][2]={0}; + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for (symNo=0; symNo<D_NSYM1SF; symNo++){ + for(ip_ind=0; ip_ind<D_NPUCCH_SF5-1; ip_ind++) { + IP_CsData_allsfavg[aa][symNo][ip_ind][0] = 0; + IP_CsData_allsfavg[aa][symNo][ip_ind][1] = 0; + } + } + } + + // compute m[], m_self + for(i=0; i<NUMBER_OF_UE_MAX; i++) { + m[i] = n3_pucch_array[i] / N_PUCCH_SF0; // N_PUCCH_SF0 = 5 + if(n3_pucch_array[i] == n3_pucch) { + m_self = i; + } + } + + for(i=0; i<NUMBER_OF_UE_MAX; i++) { + //printf("n3_pucch_array[%d]=%d, m[%d]=%d \n", i, n3_pucch_array[i], i, m[i]); + } + //printf("m_self=%d \n", m_self); + + // compute n3_pucch_sameRB[] // Not 4 not be equally divided + for(i=0, same_m_number=0; i<NUMBER_OF_UE_MAX; i++) { + if(m[i] == m[m_self]) { + n3_pucch_sameRB[same_m_number] = n3_pucch_array[i]; + same_m_number++; + } + } + //printf("same_m_number = %d \n", same_m_number); + for(i=0; i<same_m_number; i++) { + //printf("n3_pucch_sameRB[%d]=%d \n", i, n3_pucch_sameRB[i]); + } + + // compute n_oc1[], n_oc0[] + for(i=0; i<same_m_number; i++) { + n_oc0[i] = n3_pucch_sameRB[i] % N_PUCCH_SF1; //N_PUCCH_SF1 = (shortened_format==0)? 5:4; + if (N_PUCCH_SF1 == 5) { + n_oc1[i] = (3 * n_oc0[i]) % N_PUCCH_SF1; + } else { + n_oc1[i] = n_oc0[i] % N_PUCCH_SF1; + } + } + for(i=0; i<same_m_number; i++) { + //printf("n_oc0[%d]=%d, n_oc1[%d]=%d \n", i, n_oc0[i], i, n_oc1[i]); + } + + + // np_n_array[][] + for(i=0; i<same_m_number; i++) { + if (N_PUCCH_SF1 == 5) { + np_n_array[0][i] = TBL_3_SF5_GEN_N_DASH_NS[n_oc0[i]]; //slot0 + np_n_array[1][i] = TBL_3_SF5_GEN_N_DASH_NS[n_oc1[i]]; //slot1 + } else { + np_n_array[0][i] = TBL_3_SF4_GEN_N_DASH_NS[n_oc0[i]]; + np_n_array[1][i] = TBL_3_SF4_GEN_N_DASH_NS[n_oc1[i]]; + } + } + for(i=0; i<same_m_number; i++) { + //printf("np_n_array[0][%d]=%d ,np_n_array[1][%d]=%d \n", i, np_n_array[0][i], i, np_n_array[1][i]); + } + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for (symNo=0; symNo<D_NSYM1SF; symNo++){ // #define D_NSYM1SF 2*7 + slotNo = symNo / D_NSYM1SLT; + sym = symNo % D_NSYM1SLT; + + for (k=0; k<D_NSC1RB; k++) { // #define D_NSC1RB 12 + + // remove Base Sequence (c_r^*)*(r_l,m,m,n,k) = BsCshData + BsCshData[aa][symNo][k][0] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][0] * ul_ref_sigs[u][v][0][k<<1] + (int32_t)SubCarrierDeMapData[aa][symNo][k][1] * ul_ref_sigs[u][v][0][1+(k<<1)])>>15); + BsCshData[aa][symNo][k][1] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][1] * ul_ref_sigs[u][v][0][k<<1] - (int32_t)SubCarrierDeMapData[aa][symNo][k][0] * ul_ref_sigs[u][v][0][1+(k<<1)])>>15); + + if(shortened_format == 1) { + if (symNo < D_NSYM1SLT) { + np = n3_pucch % D_NPUCCH_SF4; // np = n_oc + np_n = TBL_3_SF4_GEN_N_DASH_NS[np]; // + } else { + np = n3_pucch % D_NPUCCH_SF4; // + np_n = TBL_3_SF4_GEN_N_DASH_NS[np]; // + } + //npucch_sf = D_NPUCCH_SF4;// = 4 + } else { + if (symNo < D_NSYM1SLT) { + np = n3_pucch % D_NPUCCH_SF5; + np_n = TBL_3_SF5_GEN_N_DASH_NS[np]; + } else { + np = (3 * n3_pucch) % D_NPUCCH_SF5; + np_n = TBL_3_SF5_GEN_N_DASH_NS[np]; + } + //npucch_sf = D_NPUCCH_SF5;// = 5 + } + // cyclic shift e^(-j * beta_n * k) + calctmp[0] = alphaTBL_re[(((ncs_cell[2*subframe+slotNo][sym] + np_n)%D_NSC1RB)*k)%12]; + calctmp[1] = alphaTBL_im[(((ncs_cell[2*subframe+slotNo][sym] + np_n)%D_NSC1RB)*k)%12]; + + // Channel Estimation 1A, g'(n_cs)_l,m,n + // CsData_temp = g_l,m,n,k + // remove cyclic shift BsCshData * e^(-j * beta_n * k) + CsData_temp[aa][symNo][k][0]=((((int32_t)BsCshData[aa][symNo][k][0] * calctmp[0] + (int32_t)BsCshData[aa][symNo][k][1] * calctmp[1])/ D_NSC1RB)>>15); + CsData_temp[aa][symNo][k][1]=((((int32_t)BsCshData[aa][symNo][k][1] * calctmp[0] - (int32_t)BsCshData[aa][symNo][k][0] * calctmp[1])/ D_NSC1RB)>>15); + + // Interference power for Channel Estimation 1A, No use Cyclic Shift g'(n_cs)_l,m,n + // Calculated by the cyclic shift that is not used S(ncs)_est + ip_ind = 0; + for(i=0; i<N_PUCCH_SF1; i++) { + for(j=0; j<same_m_number; j++) { //np_n_array Loop + if(shortened_format == 1) { + if(symNo < D_NSYM1SLT) { // if SF==1 slot0 + if(TBL_3_SF4_GEN_N_DASH_NS[i] == np_n_array[0][j]) { + break; + } + } else { // if SF==1 slot1 + if(TBL_3_SF4_GEN_N_DASH_NS[i] == np_n_array[1][j]) { + break; + } + } + } else { + if(symNo < D_NSYM1SLT) { // if SF==0 slot0 + if(TBL_3_SF5_GEN_N_DASH_NS[i] == np_n_array[0][j]) { + break; + } + } else { // if SF==0 slot1 + if(TBL_3_SF5_GEN_N_DASH_NS[i] == np_n_array[1][j]) { + break; + } + } + } + if(j == same_m_number - 1) { //when even once it has not been used + if(shortened_format == 1) { + calctmp[0] = alphaTBL_re[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF4_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12]; //D_NSC1RB =12 + calctmp[1] = alphaTBL_im[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF4_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12]; + } else { + calctmp[0] = alphaTBL_re[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF5_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12]; + calctmp[1] = alphaTBL_im[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF5_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12]; + } + // IP_CsData_allsfavg = g'(n_cs)_l,m,n + IP_CsData_allsfavg[aa][symNo][ip_ind][0] += ((((int32_t)BsCshData[aa][symNo][k][0] * calctmp[0] + (int32_t)BsCshData[aa][symNo][k][1] * calctmp[1]))>>15); + IP_CsData_allsfavg[aa][symNo][ip_ind][1] += ((((int32_t)BsCshData[aa][symNo][k][1] * calctmp[0] - (int32_t)BsCshData[aa][symNo][k][0] * calctmp[1]))>>15); + if((symNo == 1 || symNo == 5 || symNo == 8 || symNo == 12)) { + } + ip_ind++; + } + } + } + } + if(symNo > D_NSYM1SLT-1) { + u=u1; + v=v1; + } + } + } + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for (symNo=0; symNo<D_NSYM1SF; symNo++){ + CsData_allavg[aa][symNo][0] = 0; + CsData_allavg[aa][symNo][1] = 0; + for (k=0; k<D_NSC1RB; k++) { + CsData_allavg[aa][symNo][0] += (int16_t)((double)CsData_temp[aa][symNo][k][0]); + CsData_allavg[aa][symNo][1] += (int16_t)((double)CsData_temp[aa][symNo][k][1]); + } + } + } + + // Frequency deviation estimation + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for (k=0; k<12; k++) { + delta_theta_comp[aa][k][0] = 0; + delta_theta_comp[aa][k][1] = 0; + + delta_theta_comp[aa][k][0] += (((int32_t)CsData_temp[aa][1][k][0] * CsData_temp[aa][5][k][0] + (int32_t)((CsData_temp[aa][1][k][1])*CsData_temp[aa][5][k][1]))>>8); + delta_theta_comp[aa][k][1] += (((int32_t)CsData_temp[aa][1][k][0]*CsData_temp[aa][5][k][1] - (int32_t)((CsData_temp[aa][1][k][1])*CsData_temp[aa][5][k][0]) )>>8); + + delta_theta_comp[aa][k][0] += (((int32_t)CsData_temp[aa][8][k][0] * CsData_temp[aa][12][k][0] + (int32_t)((CsData_temp[aa][8][k][1])*CsData_temp[aa][12][k][1]))>>8); + delta_theta_comp[aa][k][1] += (((int32_t)CsData_temp[aa][8][k][0]*CsData_temp[aa][12][k][1] - (int32_t)((CsData_temp[aa][8][k][1])*CsData_temp[aa][12][k][0]))>>8); + + delta_theta[aa][k] = atan2((double)delta_theta_comp[aa][k][1], (double)delta_theta_comp[aa][k][0]) / 4.0; + } + } + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for (k=0; k<D_NSC1RB; k++) { + ChestValue[aa][0][k][0] = (int16_t)((CsData_allavg[aa][1][0] + (int16_t)(((double)CsData_allavg[aa][5][0] * cos(delta_theta[aa][k]*4)) + ((double)CsData_allavg[aa][5][1] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ; + ChestValue[aa][0][k][1] = (int16_t)((CsData_allavg[aa][1][1] + (int16_t)(((double)CsData_allavg[aa][5][1] * cos(delta_theta[aa][k]*4)) - ((double)CsData_allavg[aa][5][0] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ; + ChestValue[aa][1][k][0] = (int16_t)((CsData_allavg[aa][8][0] + (int16_t)(((double)CsData_allavg[aa][12][0] * cos(delta_theta[aa][k]*4)) + ((double)CsData_allavg[aa][12][1] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ; + ChestValue[aa][1][k][1] = (int16_t)((CsData_allavg[aa][8][1] + (int16_t)(((double)CsData_allavg[aa][12][1] * cos(delta_theta[aa][k]*4)) - ((double)CsData_allavg[aa][12][0] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ; + } + } + + *Interpw = 0; + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + if(ip_ind == 0) {//ip_ind= The total number of cyclic shift of non-use + *Interpw = 1; + break; + } + for(i=0; i<ip_ind; i++) { + IP_allavg[i] = 0; + + IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][1][i][0] * IP_CsData_allsfavg[aa][1][i][0] + (int32_t)IP_CsData_allsfavg[aa][1][i][1]*IP_CsData_allsfavg[aa][1][i][1])>>8); + IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][5][i][0] * IP_CsData_allsfavg[aa][5][i][0] + (int32_t)IP_CsData_allsfavg[aa][5][i][1]*IP_CsData_allsfavg[aa][5][i][1])>>8); + IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][8][i][0] * IP_CsData_allsfavg[aa][8][i][0] + (int32_t)IP_CsData_allsfavg[aa][8][i][1]*IP_CsData_allsfavg[aa][8][i][1])>>8); + IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][12][i][0] * IP_CsData_allsfavg[aa][12][i][0] + (int32_t)IP_CsData_allsfavg[aa][12][i][1]*IP_CsData_allsfavg[aa][12][i][1])>>8); + *Interpw += IP_allavg[i]/(2*D_NSLT1SF*frame_parms->nb_antennas_rx*ip_ind*12); + } + } + return 0; +} + +/* Channel Equalization */ +uint16_t pucchfmt3_Equalization( int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2], + int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2], + int16_t ChestValue[NB_ANTENNAS_RX][2][12][2], + LTE_DL_FRAME_PARMS *frame_parms) +{ + int16_t aa, sltNo, symNo, k; + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + sltNo = 0; + for (symNo=0; symNo<D_NSYM1SF; symNo++){ + if(symNo >= D_NSYM1SLT) { + sltNo = 1; + } + for (k=0; k<D_NSC1RB; k++){ + ChdetAfterValue_fmt3[aa][symNo][k][0] = (((int32_t)CshData_fmt3[aa][symNo][k][0] * ChestValue[aa][sltNo][k][0] + (int32_t)CshData_fmt3[aa][symNo][k][1] * ChestValue[aa][sltNo][k][1])>>8); + ChdetAfterValue_fmt3[aa][symNo][k][1] = (((int32_t)CshData_fmt3[aa][symNo][k][1] * ChestValue[aa][sltNo][k][0] - (int32_t)CshData_fmt3[aa][symNo][k][0] * ChestValue[aa][sltNo][k][1])>>8); + } + } + } + return 0; +} + +/* Frequency deviation remove AFC */ +uint16_t pucchfmt3_FrqDevRemove( int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2], + double delta_theta[NB_ANTENNAS_RX][12], + int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2], + LTE_DL_FRAME_PARMS *frame_parms ) +{ + int16_t aa, sltNo, symNo1slt, k, n; + double calctmp[2]; + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for(sltNo = 0; sltNo<D_NSLT1SF; sltNo++) + { + n=0; + for (symNo1slt=0, n=0; symNo1slt<D_NSYM1SLT; symNo1slt++){ + if(!((symNo1slt==1) || (symNo1slt==5))) { + for (k=0; k<D_NSC1RB; k++) { + calctmp[0] = cos(delta_theta[aa][k] * (n-1)); + calctmp[1] = sin(delta_theta[aa][k] * (n-1)); + + RemoveFrqDev_fmt3[aa][sltNo][n][k][0] = (int16_t)((double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][0] * calctmp[0] + + (double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][1] * calctmp[1]); + RemoveFrqDev_fmt3[aa][sltNo][n][k][1] = (int16_t)((double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][1] * calctmp[0] + - (double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][0] * calctmp[1]); + } + n++; + } + } + } + } + return 0; +} + +//for opt.Lev.2 +#define MAXROW_TBL_SF5 5 +#define MAXCLM_TBL_SF5 5 +const int16_t TBL_3_SF5[MAXROW_TBL_SF5][MAXCLM_TBL_SF5][2] = + {{ {32767,0}, {32767,0}, {32767,0}, {32767,0}, {32767,0}}, + { {32767,0}, {10126, 31163}, {-26509, 19260}, {-26509, -19260}, {10126, -31163}}, + { {32767,0}, {-26509, 19260}, {10126, -31163}, {10126, 31163}, {-26509, -19260}}, + { {32767,0}, {-26509, -19260}, {10126, 31163}, {10126, -31163}, {-26509, 19260}}, + { {32767,0}, {10126, -31163}, {-26509, -19260}, {-26509, 19260}, {10126, 31163}}}; + +#define MAXROW_TBL_SF4_fmt3 4 +#define MAXCLM_TBL_SF4 4 +const int16_t TBL_3_SF4[MAXROW_TBL_SF4_fmt3][MAXCLM_TBL_SF4][2] = + {{ {32767,0}, {32767,0}, {32767,0}, {32767,0}}, + { {32767,0}, {-32767,0}, {32767,0}, {-32767,0}}, + { {32767,0}, {32767,0}, {-32767,0}, {-32767,0}}, + { {32767,0}, {-32767,0}, {-32767,0}, {32767,0}}}; + +/* orthogonal sequence remove */ +uint16_t pucchfmt3_OrthSeqRemove( int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2], + int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2], + uint8_t shortened_format, + uint16_t n3_pucch, + LTE_DL_FRAME_PARMS *frame_parms ) +{ + int16_t aa, sltNo, n, k; + int16_t Npucch_sf; + int16_t noc; + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + for (sltNo=0; sltNo<D_NSLT1SF; sltNo++){ + if(shortened_format == 1) { + if(sltNo == 0) { + noc = n3_pucch % D_NPUCCH_SF4; + Npucch_sf = D_NPUCCH_SF5; + } else { + noc = n3_pucch % D_NPUCCH_SF4; + Npucch_sf = D_NPUCCH_SF4; + } + } else { + if(sltNo == 0) { + noc = n3_pucch % D_NPUCCH_SF5; + Npucch_sf = D_NPUCCH_SF5; + } else { + noc = (3 * n3_pucch) % D_NPUCCH_SF5; + Npucch_sf = D_NPUCCH_SF5; + } + } + for (n=0; n<Npucch_sf; n++){ + for (k=0; k<D_NSC1RB; k++) { + if ((sltNo == 1) && (shortened_format == 1)) { + Fmt3xDataRmvOrth[aa][sltNo][n][k][0] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF4[noc][n][0] + (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF4[noc][n][1])>>15); + Fmt3xDataRmvOrth[aa][sltNo][n][k][1] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF4[noc][n][0] - (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF4[noc][n][1])>>15); + } else { + Fmt3xDataRmvOrth[aa][sltNo][n][k][0] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF5[noc][n][0] + (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF5[noc][n][1])>>15); + Fmt3xDataRmvOrth[aa][sltNo][n][k][1] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF5[noc][n][0] - (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF5[noc][n][1])>>15); + } + } + } + } + } + return 0; +} + +/* averaging antenna */ +uint16_t pucchfmt3_AvgAnt( int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2], + int16_t Fmt3xDataAvgAnt[2][5][12][2], + uint8_t shortened_format, + LTE_DL_FRAME_PARMS *frame_parms ) +{ + int16_t aa, sltNo, n, k; + int16_t Npucch_sf; + + for (sltNo=0; sltNo<D_NSLT1SF; sltNo++){ + if((sltNo == 1) && (shortened_format == 1)) { + Npucch_sf = D_NPUCCH_SF4; + } else { + Npucch_sf = D_NPUCCH_SF5; + } + for (n=0; n<Npucch_sf; n++){ + for (k=0; k<D_NSC1RB; k++) { + Fmt3xDataAvgAnt[sltNo][n][k][0] = 0; + Fmt3xDataAvgAnt[sltNo][n][k][1] = 0; + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + Fmt3xDataAvgAnt[sltNo][n][k][0] += Fmt3xDataRmvOrth[aa][sltNo][n][k][0] / frame_parms->nb_antennas_rx; + Fmt3xDataAvgAnt[sltNo][n][k][1] += Fmt3xDataRmvOrth[aa][sltNo][n][k][1] / frame_parms->nb_antennas_rx; + } + } + } + } + return 0; +} + +/* averaging symbol */ +uint16_t pucchfmt3_AvgSym( int16_t Fmt3xDataAvgAnt[2][5][12][2], + int16_t Fmt3xDataAvgSym[2][12][2], + uint8_t shortened_format ) +{ + int16_t sltNo, n, k; + int16_t Npucch_sf; + + for (sltNo=0; sltNo<D_NSLT1SF; sltNo++){ + if((sltNo == 1) && (shortened_format == 1)) { + Npucch_sf = D_NPUCCH_SF4; + } else { + Npucch_sf = D_NPUCCH_SF5; + } + for (k=0; k<D_NSC1RB; k++) { + Fmt3xDataAvgSym[sltNo][k][0] = 0; + Fmt3xDataAvgSym[sltNo][k][1] = 0; + for (n=0; n<Npucch_sf; n++){ + Fmt3xDataAvgSym[sltNo][k][0] += Fmt3xDataAvgAnt[sltNo][n][k][0] / Npucch_sf; + Fmt3xDataAvgSym[sltNo][k][1] += Fmt3xDataAvgAnt[sltNo][n][k][1] / Npucch_sf; + } + } + } + return 0; +} + +/* iDFT */ +void pucchfmt3_IDft2( int16_t *x, int16_t *y ) +{ + int16_t i, k; + int16_t tmp[2]; + int16_t calctmp[D_NSC1RB*2]={0}; + + for(k=0; k<D_NSC1RB; k++) { + for (i=0; i<D_NSC1RB; i++) { + tmp[0] = alphaTBL_re[((i*k)%12)]; + tmp[1] = alphaTBL_im[((i*k)%12)]; + + calctmp[2*k] += (((int32_t)x[2*i] * tmp[0] - (int32_t)x[2*i+1] * tmp[1])>>15); + calctmp[2*k+1] += (((int32_t)x[2*i+1] * tmp[0] + (int32_t)x[2*i] * tmp[1])>>15); + } + y[2*k] = (int16_t)( (double) calctmp[2*k] / sqrt(D_NSC1RB)); + y[2*k+1] = (int16_t)((double) calctmp[2*k+1] / sqrt(D_NSC1RB)); + } +} + +/* descramble */ +uint16_t pucchfmt3_Descramble( int16_t IFFTOutData_Fmt3[2][12][2], + int16_t b[48], + uint8_t subframe, + uint32_t Nid_cell, + uint32_t rnti + ) +{ + int16_t m, k, c,i,j; + uint32_t cinit = 0; + uint32_t x1; + uint32_t s,s0,s1; + cinit = (subframe + 1) * ((2 * Nid_cell + 1)<<16) + rnti; + s0 = lte_gold_generic(&x1,&cinit,1); + s1 = lte_gold_generic(&x1,&cinit,0); + i=0; + for (m=0; m<D_NSLT1SF; m++){ + for(k=0; k<D_NSC1RB; k++) { + s = (i<32)? s0:s1; + j = (i<32)? i:(i-32); + c=((s>>j)&1); + b[i] = (IFFTOutData_Fmt3[m][k][0] * (1 - 2*c)); + i++; + + s = (i<32)? s0:s1; + j = (i<32)? i:(i-32); + c=((s>>j)&1); + b[i] = (IFFTOutData_Fmt3[m][k][1] * (1 - 2*c)); + i++; + } + } + return 0; +} + +int16_t pucchfmt3_Decode( int16_t b[48], + uint8_t subframe, + int16_t DTXthreshold, + int16_t Interpw, + uint8_t do_sr) +{ + int16_t c, i; + int32_t Rho_tmp; + int16_t c_max; + int32_t Rho_max; + int16_t bit_pattern; + + /* Is payload 6bit or 7bit? */ + if( do_sr == 1 ) { + bit_pattern = 128; + } else { + bit_pattern = 64; + } + + c=0; + Rho_tmp = 0; + for (i=0;i<48;i++) { + Rho_tmp += b[i] * (1-2*chcod_tbl[c][i]); + } + c_max = c; + Rho_max = Rho_tmp; + + for(c=1; c<bit_pattern; c++) { + Rho_tmp = 0; + for (i=0;i<48;i++) { + Rho_tmp += b[i] * (1-2*chcod_tbl[c][i]); + } + if (Rho_tmp > Rho_max) { + c_max = c; + Rho_max = Rho_tmp; + } + } + if(Interpw<1){ + Interpw=1; + } + if((Rho_max/Interpw) > DTXthreshold) { + // ***Log + return c_max; + } else { + // ***Log + return -1; + } +} + +/* PUCCH format3 << */ + uint32_t rx_pucch(PHY_VARS_eNB *eNB, PUCCH_FMT_t fmt, uint8_t UE_id, @@ -701,6 +1820,34 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; int chL; + /* PUCCH format3 >> */ + uint16_t Ret = 0; + int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] + int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] + double delta_theta[NB_ANTENNAS_RX][12]; //[Antenna][Subcarrier][Complex] + int16_t ChestValue[NB_ANTENNAS_RX][2][12][2]; //[Antenna][Slot][Subcarrier][Complex] + int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] + int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex] + int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex] + int16_t Fmt3xDataAvgAnt[2][5][12][2]; //[Slot][PUCCH_Symbol][Subcarrier][Complex] + int16_t Fmt3xDataAvgSym[2][12][2]; //[Slot][Subcarrier][Complex] + int16_t IFFTOutData_Fmt3[2][12][2]; //[Slot][Subcarrier][Complex] + int16_t b[48]; //[bit] + //int16_t IP_CsData_allavg[NB_ANTENNAS_RX][12][4][2]; //[Antenna][Symbol][Nouse Cyclic Shift][Complex] + int16_t payload_entity = -1; + int16_t Interpw; + int16_t payload_max; + + // TODO + // When using PUCCH format3, it must be an argument of rx_pucch function + uint16_t n3_pucch = 20; + uint16_t n3_pucch_array[NUMBER_OF_UE_MAX]={1}; + n3_pucch_array[0]=n3_pucch; + uint8_t do_sr = 1; + uint16_t crnti=0x1234; + int16_t DTXthreshold = 10; + /* PUCCH format3 << */ + if (first_call == 1) { for (i=0;i<10;i++) { for (j=0;j<NUMBER_OF_UE_MAX;j++) { @@ -730,7 +1877,13 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } */ - + if(fmt!=pucch_format3) { /* PUCCH format3 */ + + // TODO + // "SR+ACK/NACK" length is only 7 bits. + // This restriction will be lifted in the future. + // "CQI/PMI/RI+ACK/NACK" will be supported in the future. + if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) { LOG_E(PHY,"[eNB] rx_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift); return(-1); @@ -1278,6 +2431,83 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } else { LOG_E(PHY,"[eNB] PUCCH fmt2/2a/2b not supported\n"); } + + /* PUCCH format3 >> */ + } else { + /* SubCarrier Demap */ + Ret = pucchfmt3_subCarrierDeMapping( eNB, SubCarrierDeMapData, n3_pucch ); + if(Ret != 0) { + //***log pucchfmt3_subCarrierDeMapping Error! + return(-1); + } + + /* cyclic shift hopping remove */ + Ret = pucchfmt3_Baseseq_csh_remove( SubCarrierDeMapData, CshData_fmt3, frame_parms, subframe, eNB->ncs_cell ); + if(Ret != 0) { + //***log pucchfmt3_Baseseq_csh_remove Error! + return(-1); + } + + /* Channel Estimation */ + Ret = pucchfmt3_ChannelEstimation( SubCarrierDeMapData, delta_theta, ChestValue, &Interpw, subframe, shortened_format, frame_parms, n3_pucch, n3_pucch_array, eNB->ncs_cell ); + if(Ret != 0) { + //***log pucchfmt3_ChannelEstimation Error! + return(-1); + } + + /* Channel Equalization */ + Ret = pucchfmt3_Equalization( CshData_fmt3, ChdetAfterValue_fmt3, ChestValue, frame_parms ); + if(Ret != 0) { + //***log pucchfmt3_Equalization Error! + return(-1); + } + + /* Frequency deviation remove AFC */ + Ret = pucchfmt3_FrqDevRemove( ChdetAfterValue_fmt3, delta_theta, RemoveFrqDev_fmt3, frame_parms ); + if(Ret != 0) { + //***log pucchfmt3_FrqDevRemove Error! + return(-1); + } + + /* orthogonal sequence remove */ + Ret = pucchfmt3_OrthSeqRemove( RemoveFrqDev_fmt3, Fmt3xDataRmvOrth, shortened_format, n3_pucch, frame_parms ); + if(Ret != 0) { + //***log pucchfmt3_OrthSeqRemove Error! + return(-1); + } + + /* averaging antenna */ + pucchfmt3_AvgAnt( Fmt3xDataRmvOrth, Fmt3xDataAvgAnt, shortened_format, frame_parms ); + + /* averaging symbol */ + pucchfmt3_AvgSym( Fmt3xDataAvgAnt, Fmt3xDataAvgSym, shortened_format ); + + /* IDFT */ + pucchfmt3_IDft2( (int16_t*)Fmt3xDataAvgSym[0], (int16_t*)IFFTOutData_Fmt3[0] ); + pucchfmt3_IDft2( (int16_t*)Fmt3xDataAvgSym[1], (int16_t*)IFFTOutData_Fmt3[1] ); + + /* descramble */ + pucchfmt3_Descramble(IFFTOutData_Fmt3, b, subframe, frame_parms->Nid_cell, crnti); + + /* Is payload 6bit or 7bit? */ + if( do_sr == 1 ) { + payload_max = 7; + } else { + payload_max = 6; + } + + /* decode */ + payload_entity = pucchfmt3_Decode( b, subframe, DTXthreshold, Interpw, do_sr ); + if (payload_entity == -1) { + //***log pucchfmt3_Decode Error! + return(-1); + } + + for(i=0; i<payload_max; i++) { + *(payload+i) = (uint8_t)((payload_entity>>i) & 0x01); + } + } + /* PUCCH format3 << */ return((int32_t)stat_max); @@ -1300,7 +2530,7 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, rnti = eNB->ulsch[UE_index]->rnti; for (UE_id=0; UE_id<NB_UE_INST; UE_id++) { - if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti) + if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[subframe & 0x1][0]->crnti) break; } diff --git a/openair1/PHY/LTE_TRANSPORT/rar_tools.c b/openair1/PHY/LTE_TRANSPORT/rar_tools.c index 60fa52df16d06087a0a2513ac4cdd64999426090..2d29d8c13fc07c35e851a6f30004909ba182790e 100644 --- a/openair1/PHY/LTE_TRANSPORT/rar_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/rar_tools.c @@ -31,6 +31,7 @@ */ #include "PHY/defs.h" #include "PHY/extern.h" +#include "SCHED/defs.h" #include "SCHED/extern.h" #include "LAYER2/MAC/defs.h" #include "SCHED/defs.h" @@ -69,6 +70,7 @@ int generate_eNB_ulsch_params_from_rar(unsigned char *rar_pdu, uint8_t cqireq; uint16_t *RIV2nb_rb_LUT, *RIV2first_rb_LUT; uint16_t RIV_max; + uint16_t use_srs=0; LOG_D(PHY,"[eNB][RAPROC] generate_eNB_ulsch_params_from_rar: subframe %d (harq_pid %d)\n",subframe,harq_pid); @@ -133,8 +135,6 @@ int generate_eNB_ulsch_params_from_rar(unsigned char *rar_pdu, ulsch->beta_offset_ri_times8 = 10; ulsch->beta_offset_harqack_times8 = 16; - - ulsch->harq_processes[harq_pid]->Nsymb_pusch = 12-(frame_parms->Ncp<<1); ulsch->rnti = (((uint16_t)rar[4])<<8)+rar[5]; if (ulsch->harq_processes[harq_pid]->round == 0) { @@ -151,6 +151,19 @@ int generate_eNB_ulsch_params_from_rar(unsigned char *rar_pdu, ulsch->harq_processes[harq_pid]->round++; } + + ulsch->Msg3_active = 1; + + get_Msg3_alloc(frame_parms, + subframe, + frame, + &ulsch->Msg3_frame, + &ulsch->Msg3_subframe); + + use_srs = is_srs_occasion_common(frame_parms,ulsch->Msg3_frame,ulsch->Msg3_subframe); + 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; + #ifdef DEBUG_RAR msg("ulsch ra (eNB): harq_pid %d\n",harq_pid); msg("ulsch ra (eNB): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); @@ -225,7 +238,7 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, - ulsch->harq_processes[harq_pid]->TPC = (rar[3]>>3)&7;//rar->TPC; + ulsch->harq_processes[harq_pid]->TPC = (rar[3]>>2)&7;//rar->TPC; rballoc = (((uint16_t)(rar[1]&7))<<7)|(rar[2]>>1); cqireq=rar[3]&1; @@ -245,7 +258,7 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, if (ulsch->harq_processes[harq_pid]->nb_rb > 4) { msg("rar_tools.c: unlikely rb count for RAR grant : nb_rb > 3\n"); - return(-1); + // return(-1); } // ulsch->harq_processes[harq_pid]->Ndi = 1; diff --git a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c index 7e29d998a10e30c49d96ba934d2822d86127fe75..8381eca5e411c95d9130f93eb1e3206fa1401aa1 100644 --- a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c @@ -120,17 +120,15 @@ int compareints (const void * a, const void * b) return ( *(unsigned short*)a - *(unsigned short*)b ); } - -int32_t generate_srs_tx(PHY_VARS_UE *ue, - uint8_t eNB_id, - int16_t amp, - uint32_t subframe) +#define DEBUG_SRS +int32_t generate_srs(LTE_DL_FRAME_PARMS *frame_parms, + SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, + int32_t *txptr, + int16_t amp, + uint32_t subframe) { - LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; - int32_t **txdataF = ue->common_vars.txdataF; - uint16_t msrsb=0,Nb=0,nb,b,msrs0=0,k,Msc_RS,Msc_RS_idx,carrier_pos,symbol_offset; + uint16_t msrsb=0,Nb=0,nb,b,msrs0=0,k,Msc_RS,Msc_RS_idx,carrier_pos; uint16_t *Msc_idx_ptr; int32_t k0; //uint32_t subframe_offset; @@ -178,7 +176,7 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue, } if (k0<0) { - msg("generate_srs: invalid parameter set msrs0=%d, msrsb=%d, Nb=%d => nb=%d, k0=%d\n",msrs0,msrsb,Nb,nb,k0); + LOG_E(PHY,"generate_srs: invalid parameter set msrs0=%d, msrsb=%d, Nb=%d => nb=%d, k0=%d\n",msrs0,msrsb,Nb,nb,k0); return(-1); } @@ -188,7 +186,7 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue, if (Msc_idx_ptr) Msc_RS_idx = Msc_idx_ptr - dftsizes; else { - msg("generate_srs: index for Msc_RS=%d not found\n",Msc_RS); + LOG_E(PHY,"generate_srs: index for Msc_RS=%d not found\n",Msc_RS); return(-1); } @@ -199,29 +197,20 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue, else if (Msc_RS==144) Msc_RS_idx = 9; else { - msg("generate_srs: index for Msc_RS=%d not implemented\n",Msc_RS); + LOG_E(PHY,"generate_srs: index for Msc_RS=%d not implemented\n",Msc_RS); return(-1); } #endif #ifdef DEBUG_SRS - msg("generate_srs_tx: Msc_RS = %d, Msc_RS_idx = %d\n",Msc_RS, Msc_RS_idx); + LOG_D(PHY,"generate_srs_tx: Msc_RS = %d, Msc_RS_idx = %d, k0 = %d\n",Msc_RS, Msc_RS_idx,k0); #endif carrier_pos = (frame_parms->first_carrier_offset + k0); if (carrier_pos>frame_parms->ofdm_symbol_size) { carrier_pos -= frame_parms->ofdm_symbol_size; } - uint16_t nsymb = (frame_parms->Ncp==0) ? 14:12; - symbol_offset = (int)frame_parms->ofdm_symbol_size*((subframe*nsymb)+(nsymb-1)); - - //msg("carrier_pos = %d\n",carrier_pos); - //subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size; - //symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->ofdm_symbol_size; - - int32_t *txptr; - txptr = &txdataF[0][symbol_offset]; for (k=0; k<Msc_RS; k++) { int32_t real = ((int32_t) amp * (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][k<<1]) >> 15; @@ -245,6 +234,7 @@ int generate_srs_tx_emul(PHY_VARS_UE *phy_vars_ue,uint8_t subframe) return(0); } +#if 0 int generate_srs_rx(LTE_DL_FRAME_PARMS *frame_parms, SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, int *txdataF) @@ -285,7 +275,7 @@ int generate_srs_rx(LTE_DL_FRAME_PARMS *frame_parms, } if (k0<0) { - msg("Invalid parameter set msrs0=%d, msrsb=%d, Nb=%d => nb=%d, k0=%d\n",msrs0,msrsb,Nb,nb,k0); + LOG_E(PHY,"Invalid parameter set msrs0=%d, msrsb=%d, Nb=%d => nb=%d, k0=%d\n",msrs0,msrsb,Nb,nb,k0); return(-1); } @@ -295,7 +285,7 @@ int generate_srs_rx(LTE_DL_FRAME_PARMS *frame_parms, if (Msc_idx_ptr) Msc_RS_idx = Msc_idx_ptr - dftsizes; else { - msg("generate_srs: index for Msc_RS=%d not found\n",Msc_RS); + LOG_E(PHY,"generate_srs: index for Msc_RS=%d not found\n",Msc_RS); return(-1); } @@ -306,23 +296,21 @@ int generate_srs_rx(LTE_DL_FRAME_PARMS *frame_parms, else if (Msc_RS==144) Msc_RS_idx = 9; else { - msg("generate_srs: index for Msc_RS=%d not implemented\n",Msc_RS); + LOG_E(PHY,"generate_srs: index for Msc_RS=%d not implemented\n",Msc_RS); return(-1); } #endif #ifdef DEBUG_SRS - msg("generate_srs_rx: Msc_RS = %d, Msc_RS_idx = %d, k0=%d\n",Msc_RS, Msc_RS_idx,k0); + LOG_I(PHY,"generate_srs_rx: Msc_RS = %d, Msc_RS_idx = %d, k0=%d\n",Msc_RS, Msc_RS_idx,k0); #endif carrier_pos = (frame_parms->first_carrier_offset + k0) % frame_parms->ofdm_symbol_size; for (k=0; k<Msc_RS; k++) { - ((short*) txdataF)[carrier_pos<<2] = ul_ref_sigs_rx[0][0][Msc_RS_idx][k<<2]; - ((short*) txdataF)[(carrier_pos<<2)+1] = ul_ref_sigs_rx[0][0][Msc_RS_idx][(k<<2)+1]; - ((short*) txdataF)[(carrier_pos<<2)+2] = ul_ref_sigs_rx[0][0][Msc_RS_idx][(k<<2)+2]; - ((short*) txdataF)[(carrier_pos<<2)+3] = ul_ref_sigs_rx[0][0][Msc_RS_idx][(k<<2)+3]; + ((short*) txdataF)[carrier_pos<<1] = ul_ref_sigs_rx[0][0][Msc_RS_idx][k<<1]; + ((short*) txdataF)[(carrier_pos<<1)+1] = ul_ref_sigs_rx[0][0][Msc_RS_idx][(k<<1)+1]; carrier_pos+=2; if (carrier_pos >= frame_parms->ofdm_symbol_size) @@ -365,7 +353,7 @@ int generate_srs_rx(LTE_DL_FRAME_PARMS *frame_parms, // write_output("srs_rx.m","srsrx",txdataF,1024,2,1); return(0); } - +#endif #ifdef MAIN main() diff --git a/openair1/PHY/LTE_TRANSPORT/sss.c b/openair1/PHY/LTE_TRANSPORT/sss.c index fc5e7f0d1bd7c995002c961983e63b4c6970f681..5eada8bc9c3eef2af838b2ae7901644d0a806d29 100644 --- a/openair1/PHY/LTE_TRANSPORT/sss.c +++ b/openair1/PHY/LTE_TRANSPORT/sss.c @@ -166,6 +166,7 @@ int _do_pss_sss_extract(PHY_VARS_UE *ue, int32_t **rxdataF; + //LOG_I(PHY,"do_pss_sss_extract subframe %d \n",subframe); for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { if (frame_parms->frame_type == FDD) { @@ -180,11 +181,26 @@ int _do_pss_sss_extract(PHY_VARS_UE *ue, pss_symb = 2; sss_symb = frame_parms->symbols_per_tti-1; + if(subframe==5 || subframe==0) + { rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe&0x1)].rxdataF; sss_rxF = &rxdataF[aarx][(rx_offset + (sss_symb*(frame_parms->ofdm_symbol_size)))]; rxdataF = ue->common_vars.common_vars_rx_data_per_thread[((subframe+1)&0x1)].rxdataF; pss_rxF = &rxdataF[aarx][(rx_offset + (pss_symb*(frame_parms->ofdm_symbol_size)))]; + } + else if(subframe==6 || subframe==1) + { + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe&0x1)].rxdataF; + pss_rxF = &rxdataF[aarx][(rx_offset + (pss_symb*(frame_parms->ofdm_symbol_size)))]; + + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF; + sss_rxF = &rxdataF[aarx][(rx_offset + (sss_symb*(frame_parms->ofdm_symbol_size)))]; + } + else + { + AssertFatal(0,""); + } } //printf("extract_rbs: symbol_mod=%d, rx_offset=%d, ch_offset=%d\n",symbol_mod, @@ -204,11 +220,26 @@ int _do_pss_sss_extract(PHY_VARS_UE *ue, } else { + if(subframe==5 || subframe==0) + { rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe&0x1)].rxdataF; sss_rxF = &rxdataF[aarx][(1 + (sss_symb*(frame_parms->ofdm_symbol_size)))]; rxdataF = ue->common_vars.common_vars_rx_data_per_thread[((subframe+1)&0x1)].rxdataF; pss_rxF = &rxdataF[aarx][(1 + (pss_symb*(frame_parms->ofdm_symbol_size)))]; + } + else if(subframe==6 || subframe==1) + { + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe&0x1)].rxdataF; + pss_rxF = &rxdataF[aarx][(rx_offset + (pss_symb*(frame_parms->ofdm_symbol_size)))]; + + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF; + sss_rxF = &rxdataF[aarx][(rx_offset + (sss_symb*(frame_parms->ofdm_symbol_size)))]; + } + else + { + AssertFatal(0,""); + } } } @@ -237,18 +268,20 @@ int pss_sss_extract(PHY_VARS_UE *phy_vars_ue, } int pss_only_extract(PHY_VARS_UE *phy_vars_ue, - int32_t pss_ext[4][72]) + int32_t pss_ext[4][72], + uint8_t subframe) { static int32_t dummy[4][72]; - return _do_pss_sss_extract(phy_vars_ue, pss_ext, dummy, 1 /* doPss */, 0 /* doSss */, 0); + return _do_pss_sss_extract(phy_vars_ue, pss_ext, dummy, 1 /* doPss */, 0 /* doSss */, subframe); } int sss_only_extract(PHY_VARS_UE *phy_vars_ue, - int32_t sss_ext[4][72]) + int32_t sss_ext[4][72], + uint8_t subframe) { static int32_t dummy[4][72]; - return _do_pss_sss_extract(phy_vars_ue, dummy, sss_ext, 0 /* doPss */, 1 /* doSss */, 0); + return _do_pss_sss_extract(phy_vars_ue, dummy, sss_ext, 0 /* doPss */, 1 /* doSss */, subframe); } diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools.c b/openair1/PHY/LTE_TRANSPORT/uci_tools.c index 467b1bbc9a82824aa25d4f198a634584d2063608..fba5b0c0e3ddab470bf112e7cab28eebd627e2d1 100644 --- a/openair1/PHY/LTE_TRANSPORT/uci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/uci_tools.c @@ -168,6 +168,7 @@ void extract_CQI(void *o,UCI_format_t uci_format,LTE_eNB_UE_stats *stats, uint8_ //unsigned char rank; //UCI_format fmt; //uint8_t N_RB_DL = 25; + uint8_t i; LOG_D(PHY,"[eNB][UCI] N_RB_DL %d uci format %d\n", N_RB_DL,uci_format); switch(N_RB_DL) { @@ -275,6 +276,11 @@ void extract_CQI(void *o,UCI_format_t uci_format,LTE_eNB_UE_stats *stats, uint8_ stats->DL_cqi[1] = 24; stats->DL_pmi_dual = ((wideband_cqi_rank2_2A_5MHz *)o)->pmi; + //this translates the 2-layer PMI into a single layer PMI for the first codeword + //the PMI for the second codeword will be stats->DL_pmi_single^0x1555 + stats->DL_pmi_single = 0; + for (i=0;i<7;i++) + stats->DL_pmi_single = stats->DL_pmi_single | (((stats->DL_pmi_dual&(1<i))>>i)*2)<<2*i; break; case HLC_subband_cqi_nopmi: diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c index 9571ea6cd52823d8409a2781bdd1c2ab5fc7c6e4..9ae1dc6603e985dbb5e9480301ac1557ad3be61d 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c @@ -202,6 +202,7 @@ uint32_t ulsch_encoding(uint8_t *a, PHY_VARS_UE *ue, uint8_t harq_pid, uint8_t eNB_id, + uint8_t subframe_rx, uint8_t tmode, uint8_t control_only_flag, uint8_t Nbundled) @@ -233,7 +234,7 @@ uint32_t ulsch_encoding(uint8_t *a, LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; PHY_MEASUREMENTS *meas = &ue->measurements; LTE_UE_ULSCH_t *ulsch=ue->ulsch[eNB_id]; - LTE_UE_DLSCH_t **dlsch = ue->dlsch[eNB_id]; + LTE_UE_DLSCH_t **dlsch = ue->dlsch[0][eNB_id]; uint16_t rnti = 0xffff; if (!ulsch) { @@ -241,7 +242,7 @@ uint32_t ulsch_encoding(uint8_t *a, return(-1); } - if (harq_pid > 7) { + if (harq_pid >= 8) { LOG_E(PHY,"Illegal harq_pid %d\n",harq_pid); return(-1); } @@ -261,10 +262,10 @@ uint32_t ulsch_encoding(uint8_t *a, // fill CQI/PMI information if (ulsch->O>0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_IN); - rnti = ue->pdcch_vars[eNB_id]->crnti; + rnti = ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti; fill_CQI(ulsch,meas,0,harq_pid,ue->frame_parms.N_RB_DL,rnti, tmode,ue->sinr_eff); - LOG_D(PHY,"UE CQI\n"); + LOG_D(PHY,"ULSCH Encoding rnti %x \n", rnti); print_CQI(ulsch->o,ulsch->uci_format,0,ue->frame_parms.N_RB_DL); // save PUSCH pmi for later (transmission modes 4,5,6) @@ -961,15 +962,16 @@ uint32_t ulsch_encoding(uint8_t *a, int ulsch_encoding_emul(uint8_t *ulsch_buffer, PHY_VARS_UE *ue, uint8_t eNB_id, + uint8_t subframe_rx, uint8_t harq_pid, uint8_t control_only_flag) { LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; - LTE_UE_DLSCH_t **dlsch = ue->dlsch[eNB_id]; + LTE_UE_DLSCH_t **dlsch = ue->dlsch[0][eNB_id]; PHY_MEASUREMENTS *meas = &ue->measurements; uint8_t tmode = ue->transmission_mode[eNB_id]; - uint16_t rnti=ue->pdcch_vars[eNB_id]->crnti; + uint16_t rnti=ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti; LOG_D(PHY,"EMUL UE ulsch_encoding for eNB %d,mod_id %d, harq_pid %d rnti %x, ACK(%d,%d) \n", eNB_id,ue->Mod_id, harq_pid, rnti,ulsch->o_ACK[0],ulsch->o_ACK[1]); @@ -1003,7 +1005,7 @@ int ulsch_encoding_emul(uint8_t *ulsch_buffer, //UE_transport_info_TB_index[ue->Mod_id]+=ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; // navid: currently more than one eNB is not supported in the code UE_transport_info[ue->Mod_id][ue->CC_id].num_eNB = 1; - UE_transport_info[ue->Mod_id][ue->CC_id].rnti[0] = ue->pdcch_vars[0]->crnti; + UE_transport_info[ue->Mod_id][ue->CC_id].rnti[0] = ue->pdcch_vars[subframe_rx & 0x1][0]->crnti; UE_transport_info[ue->Mod_id][ue->CC_id].eNB_id[0] = eNB_id; UE_transport_info[ue->Mod_id][ue->CC_id].harq_pid[0] = harq_pid; UE_transport_info[ue->Mod_id][ue->CC_id].tbs[0] = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3 ; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 8edb1eaf9460443a4ebe58ceba7776c42a696ad2..51a9d1e9469d8862088c2d17fb9fe32640d2e8a1 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -418,6 +418,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { extern int oai_exit; void *td_thread(void *param) { + pthread_setname_np( pthread_self(), "td processing"); PHY_VARS_eNB *eNB = ((td_params*)param)->eNB; eNB_proc_t *proc = &eNB->proc; @@ -2001,7 +2002,7 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, #endif for (UE_id=0; UE_id<NB_UE_INST; UE_id++) { - if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti) + if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[subframe & 0x1][0]->crnti) break; } @@ -2065,9 +2066,10 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, // get local ue's ack if ((UE_index >= oai_emulation.info.first_ue_local) ||(UE_index <(oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local))) { get_ack(&eNB->frame_parms, - PHY_vars_UE_g[UE_id][CC_id]->dlsch[0][0]->harq_ack, - subframe, - eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK); + PHY_vars_UE_g[UE_id][CC_id]->dlsch[0][0][0]->harq_ack, + proc->subframe_tx, + proc->subframe_rx, + eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK,0); } else { // get remote UEs' ack eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[0] = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_ACK[0]; eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[1] = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_ACK[1]; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c index a4bcd802f5c7551a646aa025fd559f1b8f6ec3d7..6dced43b5f65b951785e9224ba5da10ef10a8bfc 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c @@ -402,7 +402,7 @@ void ulsch_modulation(int32_t **txdataF, // x1 is set in lte_gold_generic x2 = (ulsch->rnti<<14) + (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 - if (harq_pid > 7) { + if (harq_pid>=8) { printf("ulsch_modulation.c: Illegal harq_pid %d\n",harq_pid); return; } diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c index 88ac12b0a711a71bac32e18f0de528cfccd425f5..91489b83c54960eda5cd1797728ff0fc3cf07f8b 100644 --- a/openair1/PHY/MODULATION/beamforming.c +++ b/openair1/PHY/MODULATION/beamforming.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see <http://www.gnu.org/licenses/>. - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@eurecom.fr - -Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ +/* + * 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.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.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/MODULATION/beamforming.c * \brief @@ -55,7 +47,7 @@ int beam_precoding(int32_t **txdataF, int aa) { uint8_t p; - uint16_t re=0; + //uint16_t re=0; int slot_offset_F; slot_offset_F = slot*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7); diff --git a/openair1/PHY/Makefile.inc b/openair1/PHY/Makefile.inc index 1586f353c0f623853f6149ca91f313630847b92a..90094b31f8605946ba6c18f31eb070b4ff99f484 100644 --- a/openair1/PHY/Makefile.inc +++ b/openair1/PHY/Makefile.inc @@ -7,6 +7,7 @@ PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_coding.o PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_modulation.o PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_demodulation.o PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_llr_computation.o +PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_llr_computation_avx2.o PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/power_control.o PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_decoding.o PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_scrambling.o diff --git a/openair1/PHY/TOOLS/alaw_lut.h b/openair1/PHY/TOOLS/alaw_lut.h index 7e6b93c9f00d5a5926390dd2c28b8ccbddca8007..abf4b142cbd82ebac1e87db760b05a2b56463fbb 100644 --- a/openair1/PHY/TOOLS/alaw_lut.h +++ b/openair1/PHY/TOOLS/alaw_lut.h @@ -32,8 +32,16 @@ // Linear to ALaw // 16 bit signed integer (typecasted as uint16_t) to 8 bit unsigned integer -const uint8_t lin2alaw[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; +extern const uint8_t lin2alaw_if4p5[65536]; +//const uint8_t lin2alaw[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; // ALaw to Linear // 8 bit unsigned integer to 16 bit signed integer (typecasted as uint16_t) -const uint16_t alaw2lin[256] = {60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800, 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752, 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168, 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144, 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592, 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400, 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064, 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968, 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240, 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112, 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496, 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368, 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352, 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840, 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944, 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; +extern const uint16_t alaw2lin_if4p5[256]; +//const uint16_t alaw2lin[256] = {60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800, 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752, 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168, 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144, 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592, 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400, 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064, 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968, 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240, 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112, 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496, 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368, 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352, 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840, 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944, 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; + + +extern const uint8_t lin2alaw_if5[65536]; +//const uint8_t lin2alaw_if5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; +extern const uint16_t alaw2lin_if5[256]; +//const uint16_t alaw2lin_if5[256] = {60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800, 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752, 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168, 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144, 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592, 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400, 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064, 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968, 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240, 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112, 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496, 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368, 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352, 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840, 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944, 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; diff --git a/openair1/PHY/TOOLS/cadd_vv.c b/openair1/PHY/TOOLS/cadd_vv.c index 0707f02085eb112902ce57c2548b68673c60c10d..a08564daf302e5da32f96fbe8b124931437d2f5a 100644 --- a/openair1/PHY/TOOLS/cadd_vv.c +++ b/openair1/PHY/TOOLS/cadd_vv.c @@ -169,6 +169,37 @@ int add_cpx_vector32(short *x, return(0); } +int32_t sub_cpx_vector16(int16_t *x, + int16_t *y, + int16_t *z, + uint32_t N) +{ + unsigned int i; // loop counter + + __m128i *x_128; + __m128i *y_128; + __m128i *z_128; + + x_128 = (__m128i *)&x[0]; + y_128 = (__m128i *)&y[0]; + z_128 = (__m128i *)&z[0]; + + for(i=0; i<(N>>3); i++) { + z_128[0] = _mm_subs_epi16(x_128[0],y_128[0]); + + x_128++; + y_128++; + z_128++; + + } + + _mm_empty(); + _m_empty(); + return(0); +} + + + int add_real_vector64(short *x, short* y, short *z, diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c index d7c7dd3feaa6332f3ca730a4bba2404f3eb70802..7e73e58e5e6523305b4aff7ae5d64222e9d026a1 100644 --- a/openair1/PHY/TOOLS/cdot_prod.c +++ b/openair1/PHY/TOOLS/cdot_prod.c @@ -107,10 +107,10 @@ int32_t dot_product(int16_t *x, // print_shorts("mmtmp7",&mmtmp7); // convert back to integer result = _mm_cvtsi64_si32(mmtmp7); - + _mm_empty(); _m_empty(); - + return(result); #elif defined(__arm__) diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index aebab9b38f80b4e02a973b07f1262e6410fa97d6..bc631bd6ccc7768d342243fea9df2ebb6876efff 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -59,18 +59,23 @@ void multadd_complex_vector_real_scalar(int16_t *x, if (zero_flag == 1) for (n=0; n<N>>2; n++) { + // print_shorts("x_128[n]=", &x_128[n]); + // print_shorts("alpha_128", &alpha_128); y_128[n] = mulhi_int16(x_128[n],alpha_128); + // print_shorts("y_128[n]=", &y_128[n]); } else for (n=0; n<N>>2; n++) { y_128[n] = adds_int16(y_128[n],mulhi_int16(x_128[n],alpha_128)); } - + _mm_empty(); _m_empty(); } + + void multadd_real_vector_complex_scalar(int16_t *x, int16_t *alpha, int16_t *y, @@ -380,6 +385,7 @@ int rotate_cpx_vector(int16_t *x, m3 = _mm_sra_epi32(m3,shift); // shift right by shift in order to compensate for the input amplitude y_128[0] = _mm_packs_epi32(m2,m3); // pack in 16bit integers with saturation [re im re im re im re im] + //print_ints("y_128[0]=", &y_128[0]); #elif defined(__arm__) ab_re0 = vmull_s16(((int16x4_t*)xd)[0],((int16x4_t*)&bconj)[0]); diff --git a/openair1/PHY/TOOLS/cmult_vv.c b/openair1/PHY/TOOLS/cmult_vv.c index 9d5079f52b6ad938e83d9f55762f01f515639a24..f8caa0c6da0261e84d6f6ecfca7119937c637b03 100644 --- a/openair1/PHY/TOOLS/cmult_vv.c +++ b/openair1/PHY/TOOLS/cmult_vv.c @@ -28,8 +28,11 @@ #if defined(__x86_64__) || defined(__i386__) int16_t conjug[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1} ; int16_t conjug2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ; + #define simd_q15_t __m128i #define simdshort_q15_t __m64 +#define set1_int16(a) _mm_set1_epi16(a) +#define setr_int16(a0, a1, a2, a3, a4, a5, a6, a7) _mm_setr_epi16(a0, a1, a2, a3, a4, a5, a6, a7 ) #elif defined(__arm__) int16_t conjug[4]__attribute__((aligned(16))) = {-1,1,-1,1} ; #define simd_q15_t int16x8_t @@ -45,7 +48,7 @@ int mult_cpx_conj_vector(int16_t *x1, int output_shift, int madd) { - // Multiply elementwise the complex conjugate of x1 with x2. + // Multiply elementwise the complex conjugate of x1 with x2. // x1 - input 1 in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| // We assume x1 with a dinamic of 15 bit maximum // @@ -68,11 +71,12 @@ int mult_cpx_conj_vector(int16_t *x1, #if defined(__x86_64__) || defined(__i386__) simd_q15_t tmp_re,tmp_im; simd_q15_t tmpy0,tmpy1; + #elif defined(__arm__) int32x4_t tmp_re,tmp_im; int32x4_t tmp_re1,tmp_im1; - int16x4x2_t tmpy; - int32x4_t shift = vdupq_n_s32(-output_shift); + int16x4x2_t tmpy; + int32x4_t shift = vdupq_n_s32(-output_shift); #endif x1_128 = (simd_q15_t *)&x1[0]; @@ -92,7 +96,7 @@ int mult_cpx_conj_vector(int16_t *x1, tmp_im = _mm_srai_epi32(tmp_im,output_shift); tmpy0 = _mm_unpacklo_epi32(tmp_re,tmp_im); tmpy1 = _mm_unpackhi_epi32(tmp_re,tmp_im); - if (madd==0) + if (madd==0) *y_128 = _mm_packs_epi32(tmpy0,tmpy1); else *y_128 += _mm_packs_epi32(tmpy0,tmpy1); @@ -100,12 +104,12 @@ int mult_cpx_conj_vector(int16_t *x1, #elif defined(__arm__) tmp_re = vmull_s16(((simdshort_q15_t *)x1_128)[0], ((simdshort_q15_t*)x2_128)[0]); - //tmp_re = [Re(x1[0])Re(x2[0]) Im(x1[0])Im(x2[0]) Re(x1[1])Re(x2[1]) Im(x1[1])Im(x2[1])] + //tmp_re = [Re(x1[0])Re(x2[0]) Im(x1[0])Im(x2[0]) Re(x1[1])Re(x2[1]) Im(x1[1])Im(x2[1])] tmp_re1 = vmull_s16(((simdshort_q15_t *)x1_128)[1], ((simdshort_q15_t*)x2_128)[1]); - //tmp_re1 = [Re(x1[1])Re(x2[1]) Im(x1[1])Im(x2[1]) Re(x1[1])Re(x2[2]) Im(x1[1])Im(x2[2])] + //tmp_re1 = [Re(x1[1])Re(x2[1]) Im(x1[1])Im(x2[1]) Re(x1[1])Re(x2[2]) Im(x1[1])Im(x2[2])] tmp_re = vcombine_s32(vpadd_s32(vget_low_s32(tmp_re),vget_high_s32(tmp_re)), vpadd_s32(vget_low_s32(tmp_re1),vget_high_s32(tmp_re1))); - //tmp_re = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2]) Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] + //tmp_re = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2]) Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] tmp_im = vmull_s16(vrev32_s16(vmul_s16(((simdshort_q15_t*)x2_128)[0],*(simdshort_q15_t*)conjug)), ((simdshort_q15_t*)x1_128)[0]); //tmp_im = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] @@ -135,6 +139,68 @@ int mult_cpx_conj_vector(int16_t *x1, return(0); } +int mult_cpx_vector(int16_t *x1, //Q15 + int16_t *x2,//Q13 + int16_t *y, + uint32_t N, + int output_shift) +{ + // Multiply elementwise x1 with x2. + // x1 - input 1 in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| + // We assume x1 with a dinamic of 15 bit maximum + // + // x2 - input 2 in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| + // We assume x2 with a dinamic of 14 bit maximum + /// + // y - output in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| + // + // N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; + // + // output_shift - shift to be applied to generate output + uint32_t i; // loop counter + simd_q15_t *x1_128; + simd_q15_t *x2_128; + simd_q15_t *y_128; + simd_q15_t tmp_re,tmp_im; + simd_q15_t tmpy0,tmpy1; + x1_128 = (simd_q15_t *)&x1[0]; + x2_128 = (simd_q15_t *)&x2[0]; + y_128 = (simd_q15_t *)&y[0]; + //print_shorts("x1_128:",&x1_128[0]); + // print_shorts("x2_128:",&x2_128[0]); + + //right shift by 13 while p_a * x0 and 15 while + // we compute 4 cpx multiply for each loop + for(i=0; i<(N>>2); i++) { + tmp_re = _mm_sign_epi16(*x1_128,*(__m128i*)&conjug2[0]);// Q15 + //print_shorts("tmp_re1:",&tmp_re[i]); + tmp_re = _mm_madd_epi16(tmp_re,*x2_128); //Q28 + //print_ints("tmp_re2:",&tmp_re[i]); + tmp_im = _mm_shufflelo_epi16(*x1_128,_MM_SHUFFLE(2,3,0,1)); //Q15 + //print_shorts("tmp_im1:",&tmp_im[i]); + tmp_im = _mm_shufflehi_epi16(tmp_im,_MM_SHUFFLE(2,3,0,1)); //Q15 + //print_shorts("tmp_im2:",&tmp_im[i]); + tmp_im = _mm_madd_epi16(tmp_im, *x2_128); //Q28 + //print_ints("tmp_im3:",&tmp_im[i]); + tmp_re = _mm_srai_epi32(tmp_re,output_shift);//Q(28-shift) + //print_ints("tmp_re shifted:",&tmp_re[i]); + tmp_im = _mm_srai_epi32(tmp_im,output_shift); //Q(28-shift) + //print_ints("tmp_im shifted:",&tmp_im[i]); + tmpy0 = _mm_unpacklo_epi32(tmp_re,tmp_im); //Q(28-shift) + //print_ints("unpack lo :",&tmpy0[i]); + tmpy1 = _mm_unpackhi_epi32(tmp_re,tmp_im); //Q(28-shift) + //print_ints("mrc rho0:",&tmpy1[i]); + *y_128 = _mm_packs_epi32(tmpy0,tmpy1); //must be Q15 + //print_shorts("*y_128:",&y_128[i]); + x1_128++; + x2_128++; + y_128++; + } + _mm_empty(); + _m_empty(); + return(0); +} + int multadd_cpx_vector(int16_t *x1, int16_t *x2, int16_t *y, @@ -156,9 +222,7 @@ int multadd_cpx_vector(int16_t *x1, // N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; // // output_shift - shift to be applied to generate output - uint32_t i; // loop counter - simd_q15_t *x1_128; simd_q15_t *x2_128; simd_q15_t *y_128; @@ -171,12 +235,9 @@ int multadd_cpx_vector(int16_t *x1, int16x4x2_t tmpy; int32x4_t shift = vdupq_n_s32(-output_shift); #endif - x1_128 = (simd_q15_t *)&x1[0]; x2_128 = (simd_q15_t *)&x2[0]; y_128 = (simd_q15_t *)&y[0]; - - // we compute 4 cpx multiply for each loop for(i=0; i<(N>>2); i++) { #if defined(__x86_64__) || defined(__i386__) @@ -191,25 +252,19 @@ int multadd_cpx_vector(int16_t *x1, //print_ints("unpack lo:",&tmpy0[i]); tmpy1 = _mm_unpackhi_epi32(tmp_re,tmp_im); //print_ints("unpack hi:",&tmpy1[i]); - if (zero_flag == 1) *y_128 = _mm_packs_epi32(tmpy0,tmpy1); else *y_128 = _mm_adds_epi16(*y_128,_mm_packs_epi32(tmpy0,tmpy1)); //print_shorts("*y_128:",&y_128[i]); - #elif defined(__arm__) - msg("mult_cpx_vector not implemented for __arm__"); #endif x1_128++; x2_128++; y_128++; } - - _mm_empty(); _m_empty(); - return(0); -} +} \ No newline at end of file diff --git a/openair1/PHY/TOOLS/defs.h b/openair1/PHY/TOOLS/defs.h index 8f0ae402bf62dfbebd7cfa06e2162486366b0e74..542b8edba5820b37c9e4d343fef07dfc6715414a 100644 --- a/openair1/PHY/TOOLS/defs.h +++ b/openair1/PHY/TOOLS/defs.h @@ -145,6 +145,12 @@ int multadd_cpx_vector(int16_t *x1, uint32_t N, int output_shift); +int mult_cpx_vector(int16_t *x1, + int16_t *x2, + int16_t *y, + uint32_t N, + int output_shift); + // lte_dfts.c void init_fft(uint16_t size, uint8_t logsize, @@ -228,6 +234,11 @@ int32_t add_cpx_vector(int16_t *x, int16_t *y, uint32_t N); +int32_t sub_cpx_vector16(int16_t *x, + int16_t *y, + int16_t *z, + uint32_t N); + int32_t add_cpx_vector32(int16_t *x, int16_t *y, int16_t *z, diff --git a/openair1/PHY/TOOLS/file_output.c b/openair1/PHY/TOOLS/file_output.c index 1eb9f25b5aa68ae65259190c7c99166138dbfc0a..16b8b108d0fcf8cd3e262b1e09b9ffd8d7941217 100644 --- a/openair1/PHY/TOOLS/file_output.c +++ b/openair1/PHY/TOOLS/file_output.c @@ -36,9 +36,9 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d printf("Writing %d elements of type %d to %s\n",length,format,fname); - if (format == 10 || format ==11 || format == 12 ) { + if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) { fp = fopen(fname,"a+"); - } else if (format != 10 && format !=11 && format != 12 ) { + } else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) { fp = fopen(fname,"w+"); } @@ -49,7 +49,7 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d return(-1); } - if (format != 10 && format !=11 && format != 12 ) + if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) fprintf(fp,"%s = [",vname); @@ -63,7 +63,9 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d break; case 1: // complex 16-bit - + case 13: + case 14: + case 15: for (i=0; i<length<<1; i+=(2*dec)) { fprintf(fp,"%d + j*(%d)\n",((short *)data)[i],((short *)data)[i+1]); @@ -165,14 +167,13 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d fprintf(fp,"%d \n",((unsigned char *)&data)[0]); break; - } - if (format != 10 && format !=11 && format !=12 ) { + if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) { fprintf(fp,"];\n"); fclose(fp); return(0); - } else if (format == 10 || format ==11 || format == 12 ) { + } else if (format == 10 || format ==11 || format == 12 || format == 13 || format == 15) { fclose(fp); return(0); } diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c index 1ba997af17fc247e950e4ee1bb9cd5183654adba..0aaea70d7d4a95f517e6d832f2f235dd23f2fb48 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/lte_dfts.c @@ -2510,6 +2510,8 @@ const static int16_t tw64[96] __attribute__((aligned(32))) = { -30273,12539,-25330,20787,-18205,27244,-9512,31356 }; +#if 0 +/* this is defined but not used, let's comment */ const static int16_t tw64rep[192] __attribute__((aligned(32))) = { 32767,0,32609,-3212,32137,-6393,31356,-9512,32767,0,32609,-3212,32137,-6393,31356,-9512, 30272,-12540,28897,-15447,27244,-18205,25329,-20788,30272,-12540,28897,-15447,27244,-18205,25329,-20788, @@ -2524,6 +2526,7 @@ const static int16_t tw64rep[192] __attribute__((aligned(32))) = { -23170,-23170,-28898,-15447,-32138,-6393,-32610,3211,-23170,-23170,-28898,-15447,-32138,-6393,-32610,3211, -30273,12539,-25330,20787,-18205,27244,-9512,31356,-30273,12539,-25330,20787,-18205,27244,-9512,31356 }; +#endif const static int16_t tw64a[96] __attribute__((aligned(32))) = { 32767,0,32609,3212,32137,6393,31356,9512, @@ -2539,6 +2542,8 @@ const static int16_t tw64a[96] __attribute__((aligned(32))) = { -23170,23170,-28898,15447,-32138,6393,-32610,-3211, -30273,-12539,-25330,-20787,-18205,-27244,-9512,-31356 }; +#if 0 +/* this is defined but not used, let's comment */ const static int16_t tw64arep[192] __attribute__((aligned(32))) = { 32767,0,32609,3212,32137,6393,31356,9512,32767,0,32609,3212,32137,6393,31356,9512, 30272,12540,28897,15447,27244,18205,25329,20788,30272,12540,28897,15447,27244,18205,25329,20788, @@ -2553,6 +2558,7 @@ const static int16_t tw64arep[192] __attribute__((aligned(32))) = { -23170,23170,-28898,15447,-32138,6393,-32610,-3211,-23170,23170,-28898,15447,-32138,6393,-32610,-3211, -30273,-12539,-25330,-20787,-18205,-27244,-9512,-31356,-30273,-12539,-25330,-20787,-18205,-27244,-9512,-31356 }; +#endif const static int16_t tw64b[96] __attribute__((aligned(32))) = { 0,32767,-3212,32609,-6393,32137,-9512,31356, @@ -2569,6 +2575,8 @@ const static int16_t tw64b[96] __attribute__((aligned(32))) = { 12539,-30273,20787,-25330,27244,-18205,31356,-9512 }; +#if 0 +/* this is defined but not used, let's comment */ const static int16_t tw64brep[192] __attribute__((aligned(32))) = { 0,32767,-3212,32609,-6393,32137,-9512,31356,0,32767,-3212,32609,-6393,32137,-9512,31356, -12540,30272,-15447,28897,-18205,27244,-20788,25329,-12540,30272,-15447,28897,-18205,27244,-20788,25329, @@ -2583,6 +2591,7 @@ const static int16_t tw64brep[192] __attribute__((aligned(32))) = { -23170,-23170,-15447,-28898,-6393,-32138,3211,-32610,-23170,-23170,-15447,-28898,-6393,-32138,3211,-32610, 12539,-30273,20787,-25330,27244,-18205,31356,-9512,12539,-30273,20787,-25330,27244,-18205,31356,-9512 }; +#endif const static int16_t tw64c[96] __attribute__((aligned(32))) = { 0,32767,3212,32609,6393,32137,9512,31356, @@ -2599,6 +2608,8 @@ const static int16_t tw64c[96] __attribute__((aligned(32))) = { -12539,-30273,-20787,-25330,-27244,-18205,-31356,-9512 }; +#if 0 +/* this is defined but not used, let's comment */ const static int16_t tw64crep[192] __attribute__((aligned(32))) = { 0,32767,3212,32609,6393,32137,9512,31356,0,32767,3212,32609,6393,32137,9512,31356, 12540,30272,15447,28897,18205,27244,20788,25329,12540,30272,15447,28897,18205,27244,20788,25329, @@ -2613,6 +2624,7 @@ const static int16_t tw64crep[192] __attribute__((aligned(32))) = { 23170,-23170,15447,-28898,6393,-32138,-3211,-32610,23170,-23170,15447,-28898,6393,-32138,-3211,-32610, -12539,-30273,-20787,-25330,-27244,-18205,-31356,-9512,-12539,-30273,-20787,-25330,-27244,-18205,-31356,-9512 }; +#endif #if defined(__x86_64__) || defined(__i386__) diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index bc67b2095c8de5248c4619a4ae13c4239790b9cd..cea702ef7804d69da774a5eca5e9027df3a05b8f 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -84,7 +84,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_xyplot_ybounds(fdui->rxsig_t,10,70); // Time-domain channel response - fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); + fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "SRS Frequency Response (samples, abs)" ); fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color @@ -196,7 +196,8 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, bit = malloc(coded_bits_per_codeword*sizeof(float)); rxsig_t = (int16_t**) phy_vars_enb->common_vars.rxdata[eNB_id]; - chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; + //chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; + chest_t = (int16_t**) phy_vars_enb->srs_vars[UE_id].srs_ch_estimates[eNB_id]; chest_f = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates[eNB_id]; pusch_llr = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->llr; pusch_comp = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; @@ -232,8 +233,10 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size); i++) { - i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; - time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); + //i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; + i2=i; + //time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); + time2[i] = (float)i; chest_t_abs[0][i] = 10*log10((float) (1+chest_t[0][2*i2]*chest_t[0][2*i2]+chest_t[0][2*i2+1]*chest_t[0][2*i2+1])); if (chest_t_abs[0][i] > ymax) @@ -247,7 +250,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, if (chest_t[arx] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { chest_t_abs[arx][i] = 10*log10((float) (1+chest_t[arx][2*i]*chest_t[arx][2*i]+chest_t[arx][2*i+1]*chest_t[arx][2*i+1])); - + if (chest_t_abs[arx][i] > ymax) ymax = chest_t_abs[arx][i]; } @@ -340,7 +343,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, Q_pucch[ind] = (float)pucch1ab_comp[2*(ind)+1]; A_pucch[ind] = 10*log10(pucch1_comp[ind]); B_pucch[ind] = ind; - C_pucch[ind] = (float)pucch1_thres[ind]; + C_pucch[ind] = (float)pucch1_thres[ind]; } fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); @@ -490,7 +493,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, int16_t **chest_f; int16_t *pdsch_llr; int16_t *pdsch_comp; - int8_t *pdcch_llr; + int16_t *pdsch_mag; + int8_t *pdcch_llr; int16_t *pdcch_comp; int8_t *pbch_llr; int16_t *pbch_comp; @@ -510,32 +514,32 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; - if (phy_vars_ue->dlsch[eNB_id][0]!=NULL) { - harq_pid = phy_vars_ue->dlsch[eNB_id][0]->current_harq_pid; + if (phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]!=NULL) { + harq_pid = phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid; if (harq_pid>=8) return; - mcs = phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs; + mcs = phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->mcs; // Button 0 - if(!phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { + if(!phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { // we are in TM5 fl_show_object(form->button_0); } } - if (phy_vars_ue->pdcch_vars[eNB_id]!=NULL) { - num_pdcch_symbols = phy_vars_ue->pdcch_vars[eNB_id]->num_pdcch_symbols; + if (phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]!=NULL) { + num_pdcch_symbols = phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]->num_pdcch_symbols; } // coded_bits_per_codeword = frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); - if (phy_vars_ue->dlsch[eNB_id][0]!=NULL) { + if (phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]!=NULL) { coded_bits_per_codeword = get_G(frame_parms, - phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->nb_rb, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, get_Qm(mcs), - phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->Nl, num_pdcch_symbols, frame, subframe, @@ -563,11 +567,12 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id]; pbch_llr = (int8_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; - pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[eNB_id]->llr; - pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[eNB_id]->rxdataF_comp[0]; + pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]->llr; + pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]->rxdataF_comp[0]; pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->llr[0]; // stream 0 // pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0]; // stream 0 pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp0[0]; + pdsch_mag = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag0[0]; // Received signal in time domain of receive antenna 0 if (rxsig_t != NULL) { @@ -699,7 +704,14 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } fl_set_xyplot_xbounds(form->pdcch_llr,0,12*frame_parms->N_RB_DL*2*3); - fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); + if (frame_parms->N_RB_DL != 100) + { + fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); + } + else + { + LOG_D(PHY,"UE PDCCH LLR plot is bugged in 20 MHz BW, to be fixed !!!\n"); + } } // PDCCH I/Q of MF Output @@ -708,8 +720,14 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, I[i] = pdcch_comp[2*i]; Q[i] = pdcch_comp[2*i+1]; } - - fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); + if (frame_parms->N_RB_DL != 100) + { + fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); + } + else + { + LOG_D(PHY,"UE PDCCH COMP plot is bugged in 20 MHz BW, to be fixed !!!\n"); + } } // PDSCH LLRs @@ -720,7 +738,14 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword); - fl_set_xyplot_data(form->pdsch_llr,bit,llr,coded_bits_per_codeword,"","",""); + if (frame_parms->N_RB_DL != 100) + { + fl_set_xyplot_data(form->pdsch_llr,bit,llr,coded_bits_per_codeword,"","",""); + } + else + { + LOG_D(PHY,"UE PDSCH LLR plot is bugged in 20 MHz BW, to be fixed !!!\n"); + } } // PDSCH I/Q of MF Output @@ -729,8 +754,9 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, for (k=0; k<frame_parms->symbols_per_tti; k++) { for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { - I[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i]; - Q[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; + int j = (2*frame_parms->N_RB_DL*12*k)+4*i; + I[ind] = (pdsch_mag[j ]!=0? 1.0/pdsch_mag[j ]: 0.0) * pdsch_comp[j ]*1.0; + Q[ind] = (pdsch_mag[j+1]!=0? 1.0/pdsch_mag[j+1]: 0.0) * pdsch_comp[j+1]*1.0; ind++; } } diff --git a/openair1/PHY/TOOLS/lte_phy_scope.h b/openair1/PHY/TOOLS/lte_phy_scope.h index a5bcfa1ce62ae54ff99f848d465dfbf5d02cecd8..2e8ca96c3aff82f34ad1a92c7b85edd1ae7357dc 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.h +++ b/openair1/PHY/TOOLS/lte_phy_scope.h @@ -46,18 +46,21 @@ typedef struct { } FD_lte_phy_scope_enb; typedef struct { - FL_FORM * lte_phy_scope_ue; - FL_OBJECT * rxsig_t; - FL_OBJECT * chest_f; - FL_OBJECT * chest_t; - FL_OBJECT * pbch_comp; - FL_OBJECT * pbch_llr; - FL_OBJECT * pdcch_comp; - FL_OBJECT * pdcch_llr; - FL_OBJECT * pdsch_comp; - FL_OBJECT * pdsch_llr; - FL_OBJECT * pdsch_tput; - FL_OBJECT * button_0; + FL_FORM * lte_phy_scope_ue; + FL_OBJECT * rxsig_t; + FL_OBJECT * chest_f; + FL_OBJECT * chest_t; + FL_OBJECT * pbch_comp; + FL_OBJECT * pbch_llr; + FL_OBJECT * pdcch_comp; + FL_OBJECT * pdcch_llr; + FL_OBJECT * pdsch_comp; + FL_OBJECT * pdsch_llr; + FL_OBJECT * pdsch_comp1; + FL_OBJECT * pdsch_llr1; + FL_OBJECT * pdsch_tput; + FL_OBJECT * button_0; + } FD_lte_phy_scope_ue; FD_lte_phy_scope_enb * create_lte_phy_scope_enb( void ); @@ -76,7 +79,4 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, - - - #endif /* FD_lte_scope_h_ */ diff --git a/openair1/PHY/TOOLS/lte_phy_scope_tm4.c b/openair1/PHY/TOOLS/lte_phy_scope_tm4.c new file mode 100644 index 0000000000000000000000000000000000000000..92a0d9f218e2ebedc09ecbdcf4eecccfa55ad022 --- /dev/null +++ b/openair1/PHY/TOOLS/lte_phy_scope_tm4.c @@ -0,0 +1,800 @@ +/* + * 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.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.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 + */ + +/* Form definition file generated by fdesign */ +#include <stdlib.h> +#include "lte_phy_scope.h" +#define TPUT_WINDOW_LENGTH 100 +int otg_enabled; +FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW}; +float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; +float tput_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; +float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; +float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; +float tput_ue_max[NUMBER_OF_UE_MAX] = {0}; +static void ia_receiver_on_off( FL_OBJECT *button, long arg) +{ + if (fl_get_button(button)) { + fl_set_object_label(button, "IA Receiver ON"); + // PHY_vars_UE_g[0][0]->use_ia_receiver = 1; + fl_set_object_color(button, FL_GREEN, FL_GREEN); + } else { + fl_set_object_label(button, "IA Receiver OFF"); + // PHY_vars_UE_g[0][0]->use_ia_receiver = 0; + fl_set_object_color(button, FL_RED, FL_RED); + } +} +static void dl_traffic_on_off( FL_OBJECT *button, long arg) +{ + if (fl_get_button(button)) { + fl_set_object_label(button, "DL Traffic ON"); + otg_enabled = 1; + fl_set_object_color(button, FL_GREEN, FL_GREEN); + } else { + fl_set_object_label(button, "DL Traffic OFF"); + otg_enabled = 0; + fl_set_object_color(button, FL_RED, FL_RED); + } +} +FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) +{ + FL_OBJECT *obj; + FD_lte_phy_scope_enb *fdui = fl_malloc( sizeof *fdui ); + // Define form + fdui->lte_phy_scope_enb = fl_bgn_form( FL_NO_BOX, 800, 800 ); + // This the whole UI box + obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 800, "" ); + fl_set_object_color( obj, FL_BLACK, FL_BLACK ); + // Received signal + fdui->rxsig_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)" ); + fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color + fl_set_xyplot_ybounds(fdui->rxsig_t,10,70); + // Time-domain channel response + fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); + fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color + // Frequency-domain channel response + fdui->chest_f = fl_add_xyplot( FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)" ); + fl_set_object_boxtype( fdui->chest_f, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->chest_f, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->chest_f, FL_WHITE ); // Label color + fl_set_xyplot_ybounds( fdui->chest_f,30,70); + // LLR of PUSCH + fdui->pusch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 260, 500, 200, "PUSCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pusch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pusch_llr, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pusch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pusch_llr,2); + // I/Q PUSCH comp + fdui->pusch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 260, 240, 200, "PUSCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pusch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pusch_comp, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pusch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pusch_comp,2); + fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); + // I/Q PUCCH comp (format 1) + fdui->pucch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH1 Energy (SR)" ); + fl_set_object_boxtype( fdui->pucch_comp1, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pucch_comp1, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pucch_comp1, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pucch_comp1,2); + // fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); + // I/Q PUCCH comp (fromat 1a/b) + fdui->pucch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 600, 240, 100, "PUCCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pucch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pucch_comp, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pucch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pucch_comp,2); + // fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); + // Throughput on PUSCH + fdui->pusch_tput = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 480, 500, 100, "PUSCH Throughput [frame]/[kbit/s]" ); + fl_set_object_boxtype( fdui->pusch_tput, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pusch_tput, FL_BLACK, FL_WHITE ); + fl_set_object_lcolor( fdui->pusch_tput, FL_WHITE ); // Label color + // Generic eNB Button + fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 20, 600, 240, 40, "" ); + fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); + fl_set_button(fdui->button_0,0); + otg_enabled = 0; + fl_set_object_label(fdui->button_0, "DL Traffic OFF"); + fl_set_object_color(fdui->button_0, FL_RED, FL_RED); + fl_set_object_callback(fdui->button_0, dl_traffic_on_off, 0 ); + fl_end_form( ); + fdui->lte_phy_scope_enb->fdui = fdui; + return fdui; +} +void phy_scope_eNB(FD_lte_phy_scope_enb *form, + PHY_VARS_eNB *phy_vars_enb, + int UE_id) +{ + int eNB_id = 0; + int i,i2,arx,atx,ind,k; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->frame_parms; + int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti; + uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; + uint8_t nb_antennas_tx = 1; // frame_parms->nb_antennas_tx; // in LTE Rel. 8 and 9 only a single transmit antenna is assumed at the UE + int16_t **rxsig_t; + int16_t **chest_t; + int16_t **chest_f; + int16_t *pusch_llr; + int16_t *pusch_comp; + int32_t *pucch1_comp; + int32_t *pucch1_thres; + int32_t *pucch1ab_comp; + float Re,Im,ymax; + float *llr, *bit; + float I[nsymb_ce*2], Q[nsymb_ce*2]; + float I_pucch[10240],Q_pucch[10240],A_pucch[10240],B_pucch[10240],C_pucch[10240]; + float rxsig_t_dB[nb_antennas_rx][FRAME_LENGTH_COMPLEX_SAMPLES]; + float chest_t_abs[nb_antennas_rx][frame_parms->ofdm_symbol_size]; + float *chest_f_abs; + float time[FRAME_LENGTH_COMPLEX_SAMPLES]; + float time2[2048]; + float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; + int frame = phy_vars_enb->proc.proc_rxtx[0].frame_tx; + uint32_t total_dlsch_bitrate = phy_vars_enb->total_dlsch_bitrate; + int coded_bits_per_codeword = 0; + uint8_t harq_pid; // in TDD config 3 it is sf-2, i.e., can be 0,1,2 + int mcs = 0; + // choose max MCS to compute coded_bits_per_codeword + if (phy_vars_enb->ulsch[UE_id]!=NULL) { + for (harq_pid=0; harq_pid<3; harq_pid++) { + mcs = cmax(phy_vars_enb->ulsch[UE_id]->harq_processes[harq_pid]->mcs,mcs); + } + } + coded_bits_per_codeword = frame_parms->N_RB_UL*12*get_Qm(mcs)*frame_parms->symbols_per_tti; + chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); + llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero + bit = malloc(coded_bits_per_codeword*sizeof(float)); + rxsig_t = (int16_t**) phy_vars_enb->common_vars.rxdata[eNB_id]; + chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; + chest_f = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates[eNB_id]; + pusch_llr = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->llr; + pusch_comp = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; + pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; + pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; + pucch1ab_comp = (int32_t*) phy_vars_enb->pucch1ab_stats[UE_id]; + // Received signal in time domain of receive antenna 0 + if (rxsig_t != NULL) { + if (rxsig_t[0] != NULL) { + for (i=0; i<FRAME_LENGTH_COMPLEX_SAMPLES; i++) { + rxsig_t_dB[0][i] = 10*log10(1.0+(float) ((rxsig_t[0][2*i])*(rxsig_t[0][2*i])+(rxsig_t[0][2*i+1])*(rxsig_t[0][2*i+1]))); + time[i] = (float) i; + } + fl_set_xyplot_data(form->rxsig_t,time,rxsig_t_dB[0],FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); + } + for (arx=1; arx<nb_antennas_rx; arx++) { + if (rxsig_t[arx] != NULL) { + for (i=0; i<FRAME_LENGTH_COMPLEX_SAMPLES; i++) { + rxsig_t_dB[arx][i] = 10*log10(1.0+(float) ((rxsig_t[arx][2*i])*(rxsig_t[arx][2*i])+(rxsig_t[arx][2*i+1])*(rxsig_t[arx][2*i+1]))); + } + fl_add_xyplot_overlay(form->rxsig_t,arx,time,rxsig_t_dB[arx],FRAME_LENGTH_COMPLEX_SAMPLES,rx_antenna_colors[arx]); + } + } + } + // Channel Impulse Response + if (chest_t != NULL) { + ymax = 0; + if (chest_t[0] !=NULL) { + for (i=0; i<(frame_parms->ofdm_symbol_size); i++) { + i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; + time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); + chest_t_abs[0][i] = 10*log10((float) (1+chest_t[0][2*i2]*chest_t[0][2*i2]+chest_t[0][2*i2+1]*chest_t[0][2*i2+1])); + if (chest_t_abs[0][i] > ymax) + ymax = chest_t_abs[0][i]; + } + fl_set_xyplot_data(form->chest_t,time2,chest_t_abs[0],(frame_parms->ofdm_symbol_size),"","",""); + } + for (arx=1; arx<nb_antennas_rx; arx++) { + if (chest_t[arx] !=NULL) { + for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { + chest_t_abs[arx][i] = 10*log10((float) (1+chest_t[arx][2*i]*chest_t[arx][2*i]+chest_t[arx][2*i+1]*chest_t[arx][2*i+1])); + if (chest_t_abs[arx][i] > ymax) + ymax = chest_t_abs[arx][i]; + } + fl_add_xyplot_overlay(form->chest_t,arx,time,chest_t_abs[arx],(frame_parms->ofdm_symbol_size>>3),rx_antenna_colors[arx]); + fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); + } + } + // Avoid flickering effect + // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); + fl_set_xyplot_ybounds(form->chest_t,0,ymax); + } + // Channel Frequency Response + if (chest_f != NULL) { + ind = 0; + for (atx=0; atx<nb_antennas_tx; atx++) { + for (arx=0; arx<nb_antennas_rx; arx++) { + if (chest_f[(atx<<1)+arx] != NULL) { + for (k=0; k<nsymb_ce; k++) { + freq[ind] = (float)ind; + Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); + Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); + chest_f_abs[ind] = (short)10*log10(1.0+((double)Re*Re + (double)Im*Im)); + ind++; + } + } + } + } + // tx antenna 0 + fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); + fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,3); + fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); + fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + for (arx=1; arx<nb_antennas_rx; arx++) { + fl_add_xyplot_overlay(form->chest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } + // other tx antennas + if (nb_antennas_tx > 1) { + if (nb_antennas_rx > 1) { + for (atx=1; atx<nb_antennas_tx; atx++) { + for (arx=0; arx<nb_antennas_rx; arx++) { + fl_add_xyplot_overlay(form->chest_f,(atx<<1)+arx,&freq[((atx<<1)+arx)*nsymb_ce],&chest_f_abs[((atx<<1)+arx)*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } + } + } else { // 1 rx antenna + atx=1; + arx=0; + fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } + } + } + // PUSCH LLRs + if (pusch_llr != NULL) { + for (i=0; i<coded_bits_per_codeword; i++) { + llr[i] = (float) pusch_llr[i]; + bit[i] = (float) i; + } + fl_set_xyplot_data(form->pusch_llr,bit,llr,coded_bits_per_codeword,"","",""); + } + // PUSCH I/Q of MF Output + if (pusch_comp!=NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_UL; i++) { + I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; + Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; + ind++; + } + } + fl_set_xyplot_data(form->pusch_comp,I,Q,ind,"","",""); + } + // PUSCH I/Q of MF Output + if (pucch1ab_comp!=NULL) { + for (ind=0; ind<10240; ind++) { + I_pucch[ind] = (float)pucch1ab_comp[2*(ind)]; + Q_pucch[ind] = (float)pucch1ab_comp[2*(ind)+1]; + A_pucch[ind] = 10*log10(pucch1_comp[ind]); + B_pucch[ind] = ind; + C_pucch[ind] = (float)pucch1_thres[ind]; + } + fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); + fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); + fl_add_xyplot_overlay(form->pucch_comp1,1,B_pucch,C_pucch,1024,FL_RED); + fl_set_xyplot_ybounds(form->pucch_comp,-5000,5000); + fl_set_xyplot_xbounds(form->pucch_comp,-5000,5000); + fl_set_xyplot_ybounds(form->pucch_comp1,0,80); + } + // PUSCH Throughput + memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); + memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); + tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame; + tput_enb[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; + fl_set_xyplot_data(form->pusch_tput,tput_time_enb[UE_id],tput_enb[UE_id],TPUT_WINDOW_LENGTH,"","",""); + // fl_get_xyplot_ybounds(form->pusch_tput,&ymin,&ymax); + // fl_set_xyplot_ybounds(form->pusch_tput,0,ymax); + fl_check_forms(); + free(llr); + free(bit); + free(chest_f_abs); +} +FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) { + FL_OBJECT *obj; + FD_lte_phy_scope_ue *fdui = fl_malloc( sizeof *fdui ); + // Define form + fdui->lte_phy_scope_ue = fl_bgn_form( FL_NO_BOX, 800, 1000 ); + // This the whole UI box + obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 1000, "" ); + fl_set_object_color( obj, FL_BLACK, FL_BLACK ); + // Received signal + fdui->rxsig_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)" ); + fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color + fl_set_xyplot_ybounds(fdui->rxsig_t,30,70); + // Time-domain channel response + fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); + fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color + // Frequency-domain channel response + fdui->chest_f = fl_add_xyplot( FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)" ); + fl_set_object_boxtype( fdui->chest_f, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->chest_f, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->chest_f, FL_WHITE ); // Label color + fl_set_xyplot_ybounds( fdui->chest_f,30,70); + /* + // LLR of PBCH + fdui->pbch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 260, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pbch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pbch_llr, FL_BLACK, FL_GREEN ); + fl_set_object_lcolor( fdui->pbch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pbch_llr,2); + fl_set_xyplot_xgrid( fdui->pbch_llr,FL_GRID_MAJOR); + fl_set_xyplot_xbounds( fdui->pbch_llr,0,1920); + // I/Q PBCH comp + fdui->pbch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 260, 240, 100, "PBCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pbch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pbch_comp, FL_BLACK, FL_GREEN ); + fl_set_object_lcolor( fdui->pbch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pbch_comp,2); + fl_set_xyplot_xbounds( fdui->pbch_comp,-100,100); + fl_set_xyplot_ybounds( fdui->pbch_comp,-100,100); + // LLR of PDCCH + fdui->pdcch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 380, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pdcch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdcch_llr, FL_BLACK, FL_CYAN ); + fl_set_object_lcolor( fdui->pdcch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdcch_llr,2); + // I/Q PDCCH comp + fdui->pdcch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 380, 240, 100, "PDCCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pdcch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdcch_comp, FL_BLACK, FL_CYAN ); + fl_set_object_lcolor( fdui->pdcch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdcch_comp,2); + fl_set_xyplot_xgrid( fdui->pdcch_llr,FL_GRID_MAJOR); + */ + int offset=240; + // LLR of PDSCH + fdui->pdsch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 500-offset, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pdsch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_llr, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_llr,2); + fl_set_xyplot_xgrid( fdui->pdsch_llr,FL_GRID_MAJOR); + // I/Q PDSCH comp + fdui->pdsch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 500-offset, 240, 200, "PDSCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pdsch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_comp, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_comp,2); + // LLR of PDSCH + fdui->pdsch_llr1 = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 720-offset, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pdsch_llr1, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_llr1, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_llr1, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_llr1,2); + fl_set_xyplot_xgrid( fdui->pdsch_llr1,FL_GRID_MAJOR); + // I/Q PDSCH comp + fdui->pdsch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 720-offset, 240, 200, "PDSCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pdsch_comp1, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_comp1, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_comp1, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_comp1,2); + /* + // Throughput on PDSCH + fdui->pdsch_tput = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 720, 500, 100, "PDSCH Throughput [frame]/[kbit/s]" ); + fl_set_object_boxtype( fdui->pdsch_tput, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_tput, FL_BLACK, FL_WHITE ); + fl_set_object_lcolor( fdui->pdsch_tput, FL_WHITE ); // Label color + // Generic UE Button + fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 540, 720, 240, 40, "" ); + fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); + //openair_daq_vars.use_ia_receiver = 0; + fl_set_button(fdui->button_0,0); + fl_set_object_label(fdui->button_0, "IA Receiver OFF"); + fl_set_object_color(fdui->button_0, FL_RED, FL_RED); + fl_set_object_callback(fdui->button_0, ia_receiver_on_off, 0 ); + fl_hide_object(fdui->button_0); + */ + fl_end_form( ); + fdui->lte_phy_scope_ue->fdui = fdui; + return fdui; +} +void phy_scope_UE(FD_lte_phy_scope_ue *form, + PHY_VARS_UE *phy_vars_ue, + int eNB_id, + int UE_id, + uint8_t subframe){ + int i,arx,atx,ind,k; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; + int nsymb_ce = frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti; + uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; + uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_eNB; + int16_t **rxsig_t; + int16_t **chest_t; + int16_t **chest_f; + int16_t *pdsch_llr,*pdsch_llr1; + int16_t *pdsch_comp,*pdsch_comp1; + int16_t *pdsch_mag0,*pdsch_mag1,*pdsch_magb0,*pdsch_magb1; + int8_t *pdcch_llr; + int16_t *pdcch_comp; + int8_t *pbch_llr; + int16_t *pbch_comp; + float Re,Im,ymax=1; + int num_pdcch_symbols=3; + float *llr0, *bit0, *llr1, *bit1, *chest_f_abs, llr_pbch[1920], bit_pbch[1920], *llr_pdcch, *bit_pdcch; + float *I, *Q; + float rxsig_t_dB[nb_antennas_rx][FRAME_LENGTH_COMPLEX_SAMPLES]; + float **chest_t_abs; + float time[FRAME_LENGTH_COMPLEX_SAMPLES]; + float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; + int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; + uint32_t total_dlsch_bitrate = phy_vars_ue->bitrate[eNB_id]; + int coded_bits_per_codeword0=0,coded_bits_per_codeword1=1; + int mod0,mod1; + int mcs0 = 0; + int mcs1=0; + unsigned char harq_pid = 0; + int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; + if (phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]!=NULL) { + harq_pid = phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid; + if (harq_pid>=8) + return; + mcs0 = phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->mcs; + // Button 0 + /* + if(!phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { + // we are in TM5 + fl_show_object(form->button_0); + } + */ + } + if (phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]!=NULL) { + harq_pid = phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]->current_harq_pid; + if (harq_pid>=8) + return; + mcs1 = phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]->harq_processes[harq_pid]->mcs; + } + if (phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]!=NULL) { + num_pdcch_symbols = phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]->num_pdcch_symbols; + } + // coded_bits_per_codeword = frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); + if (phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]!=NULL) { + mod0 = get_Qm(mcs0); + coded_bits_per_codeword0 = get_G(frame_parms, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->nb_rb, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + get_Qm(mcs0), + phy_vars_ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->Nl, + num_pdcch_symbols, + frame, + subframe, + beamforming_mode); + } else { + coded_bits_per_codeword0 = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); + mod0=0; + } + if (phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]!=NULL) { + mod1 = get_Qm(mcs1); + coded_bits_per_codeword1 = get_G(frame_parms, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]->harq_processes[harq_pid]->nb_rb, + phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]->harq_processes[harq_pid]->rb_alloc_even, + get_Qm(mcs1), + phy_vars_ue->dlsch[subframe&0x1][eNB_id][1]->harq_processes[harq_pid]->Nl, + num_pdcch_symbols, + frame, + subframe, + beamforming_mode); + } else { + coded_bits_per_codeword1 = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); + mod1=0; + } + I = (float*) calloc(nsymb_ce*2,sizeof(float)); + Q = (float*) calloc(nsymb_ce*2,sizeof(float)); + chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*)); + for (arx=0;arx<nb_antennas_rx;arx++) { + chest_t_abs[arx] = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); + } + chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); + llr0 = (float*) calloc(coded_bits_per_codeword0,sizeof(float)); // init to zero + bit0 = malloc(coded_bits_per_codeword0*sizeof(float)); + llr1 = (float*) calloc(coded_bits_per_codeword1,sizeof(float)); // init to zero + bit1 = malloc(coded_bits_per_codeword1*sizeof(float)); + llr_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero + bit_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); + rxsig_t = (int16_t**) phy_vars_ue->common_vars.rxdata; + chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates_time[eNB_id]; + chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id]; + pbch_llr = (int8_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; + pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; + pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]->llr; + pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[subframe&0x1][eNB_id]->rxdataF_comp[0]; + pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->llr[0]; // stream 0 + pdsch_llr1 = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->llr[1]; // stream 1 + pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp0[0]; + //pdsch_comp = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[subframe&0x1][eNB_id]->rxdataF_ext[0]; + //pdsch_comp1 = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[subframe&0x1][eNB_id]->rxdataF_ext[1]; + pdsch_comp1 = (int16_t*) (phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[0][0])[0]; + //pdsch_comp1 = (int16_t*) (phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext[0][0])[0]; + pdsch_mag0 = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag0[0]; + pdsch_mag1 = (int16_t*) (phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag1[0][0])[0]; + pdsch_magb0 = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_magb0[0]; + pdsch_magb1 = (int16_t*) (phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_magb1[0][0])[0]; + fl_freeze_form(form->lte_phy_scope_ue); + // Received signal in time domain of receive antenna 0 + if (rxsig_t != NULL) { + if (rxsig_t[0] != NULL) { + for (i=0; i<FRAME_LENGTH_COMPLEX_SAMPLES; i++) { + rxsig_t_dB[0][i] = 10*log10(1.0+(float) ((rxsig_t[0][2*i])*(rxsig_t[0][2*i])+(rxsig_t[0][2*i+1])*(rxsig_t[0][2*i+1]))); + time[i] = (float) i; + } + fl_set_xyplot_data(form->rxsig_t,time,rxsig_t_dB[0],FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); + } + for (arx=1;arx<nb_antennas_rx;arx++) { + if (rxsig_t[arx] != NULL) { + for (i=0; i<FRAME_LENGTH_COMPLEX_SAMPLES; i++) { + rxsig_t_dB[arx][i] = 10*log10(1.0+(float) ((rxsig_t[arx][2*i])*(rxsig_t[arx][2*i])+(rxsig_t[arx][2*i+1])*(rxsig_t[arx][2*i+1]))); + } + fl_add_xyplot_overlay(form->rxsig_t,arx,time,rxsig_t_dB[arx],FRAME_LENGTH_COMPLEX_SAMPLES,rx_antenna_colors[arx]); + } + } + } + // Channel Impulse Response (still repeated format) + if (chest_t != NULL) { + ymax = 0; + if (chest_t[0] !=NULL) { + for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { + chest_t_abs[0][i] = (float) (chest_t[0][4*i]*chest_t[0][4*i]+chest_t[0][4*i+1]*chest_t[0][4*i+1]); + if (chest_t_abs[0][i] > ymax) + ymax = chest_t_abs[0][i]; + } + fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size>>3),"","",""); + } + for (arx=1; arx<nb_antennas_rx; arx++) { + if (chest_t[arx] !=NULL) { + for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { + chest_t_abs[arx][i] = (float) (chest_t[arx][4*i]*chest_t[arx][4*i]+chest_t[arx][4*i+1]*chest_t[arx][4*i+1]); + if (chest_t_abs[arx][i] > ymax) + ymax = chest_t_abs[arx][i]; + } + fl_add_xyplot_overlay(form->chest_t,arx,time,chest_t_abs[arx],(frame_parms->ofdm_symbol_size>>3),rx_antenna_colors[arx]); + fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); + } + } + // Avoid flickering effect + // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); + fl_set_xyplot_ybounds(form->chest_t,0,ymax); + } + // Channel Frequency Response (includes 5 complex sample for filter) + if (chest_f != NULL) { + ind = 0; + for (atx=0;atx<nb_antennas_tx;atx++) { + for (arx=0;arx<nb_antennas_rx;arx++) { + if (chest_f[(atx<<1)+arx] != NULL) { + for (k=0; k<nsymb_ce; k++) { + freq[ind] = (float)ind; + Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); + Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); + chest_f_abs[ind] = (short)10*log10(1.0+((double)Re*Re + (double)Im*Im)); + ind++; + } + } + } + } + // tx antenna 0 + fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); + //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); + // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); + fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); + fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + for (arx=1;arx<nb_antennas_rx;arx++) { + fl_add_xyplot_overlay(form->chest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } + // other tx antennas + if (nb_antennas_tx > 1) { + if (nb_antennas_rx > 1) { + for (atx=1;atx<nb_antennas_tx;atx++) { + for (arx=0;arx<nb_antennas_rx;arx++) { + fl_add_xyplot_overlay(form->chest_f,(atx<<1)+arx,&freq[((atx<<1)+arx)*nsymb_ce],&chest_f_abs[((atx<<1)+arx)*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } + } + } else { // 1 rx antenna + atx=1; arx=0; + fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } + } + } + /* + // PBCH LLRs + if (pbch_llr != NULL) { + for (i=0; i<1920;i++) { + llr_pbch[i] = (float) pbch_llr[i]; + bit_pbch[i] = (float) i; + } + fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,1920,"","",""); + } + // PBCH I/Q of MF Output + if (pbch_comp!=NULL) { + for (i=0; i<72*2; i++) { + I[i] = pbch_comp[2*i]; + Q[i] = pbch_comp[2*i+1]; + } + fl_set_xyplot_data(form->pbch_comp,I,Q,72*2,"","",""); + } + // PDCCH LLRs + if (pdcch_llr != NULL) { + for (i=0; i<12*frame_parms->N_RB_DL*2*num_pdcch_symbols;i++) { + llr_pdcch[i] = (float) pdcch_llr[i]; + bit_pdcch[i] = (float) i; + } + fl_set_xyplot_xbounds(form->pdcch_llr,0,12*frame_parms->N_RB_DL*2*3); + fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); + } + // PDCCH I/Q of MF Output + if (pdcch_comp!=NULL) { + for (i=0; i<12*frame_parms->N_RB_DL*num_pdcch_symbols; i++) { + I[i] = pdcch_comp[2*i]; + Q[i] = pdcch_comp[2*i+1]; + } + fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); + } + */ + // PDSCH LLRs CW0 + if (pdsch_llr != NULL) { + for (i=0; i<coded_bits_per_codeword0; i++) { + llr0[i] = (float) pdsch_llr[i]; + bit0[i] = (float) i; + } + fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword0); + fl_set_xyplot_data(form->pdsch_llr,bit0,llr0,coded_bits_per_codeword0,"","",""); + } + // PDSCH I/Q of MF Output + if (pdsch_comp!=NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i]; + Q[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; + ind++; + } + } + fl_set_xyplot_data(form->pdsch_comp,I,Q,ind,"","",""); + } + if (pdsch_mag0 != NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + Q[ind] = pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + ind++; + } + } + fl_add_xyplot_overlay(form->pdsch_comp,1,I,Q,ind,FL_GREEN); + } + if (pdsch_magb0 != NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + Q[ind] = pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + ind++; + } + } + fl_add_xyplot_overlay(form->pdsch_comp,2,I,Q,ind,FL_RED); + } + if ((pdsch_mag0 != NULL) && (pdsch_magb0 != NULL)) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = + (pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i]+ + pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i])* + cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + Q[ind] = + (pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]+ + pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i+1])* + sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + ind++; + } + } + fl_add_xyplot_overlay(form->pdsch_comp,3,I,Q,ind,FL_BLUE); + } + // PDSCH LLRs CW1 + if (pdsch_llr1 != NULL) { + for (i=0; i<coded_bits_per_codeword1; i++) { + llr1[i] = (float) pdsch_llr1[i]; + bit1[i] = (float) i; + } + fl_set_xyplot_xbounds(form->pdsch_llr1,0,coded_bits_per_codeword1); + fl_set_xyplot_data(form->pdsch_llr1,bit1,llr1,coded_bits_per_codeword1,"","",""); + } + // PDSCH I/Q of MF Output + if (pdsch_comp1!=NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_comp1[(2*frame_parms->N_RB_DL*12*k)+4*i]; + Q[ind] = pdsch_comp1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; + ind++; + } + } + fl_set_xyplot_data(form->pdsch_comp1,I,Q,ind,"","",""); + } + if (pdsch_mag1 != NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + Q[ind] = pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + ind++; + } + } + fl_add_xyplot_overlay(form->pdsch_comp1,1,I,Q,ind,FL_GREEN); + } + if (pdsch_magb1 != NULL) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + Q[ind] = pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + ind++; + } + } + fl_add_xyplot_overlay(form->pdsch_comp1,2,I,Q,ind,FL_RED); + } + if ((pdsch_mag1 != NULL) && (pdsch_magb1 != NULL)) { + ind=0; + for (k=0; k<frame_parms->symbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = + (pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i]+ + pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i])* + cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + Q[ind] = + (pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]+ + pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i+1])* + sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + ind++; + } + } + fl_add_xyplot_overlay(form->pdsch_comp1,3,I,Q,ind,FL_BLUE); + } + /* + // PDSCH Throughput + memcpy((void*)tput_time_ue[UE_id],(void*)&tput_time_ue[UE_id][1],(TPUT_WINDOW_LENGTH-1)*sizeof(float)); + memcpy((void*)tput_ue[UE_id],(void*)&tput_ue[UE_id][1],(TPUT_WINDOW_LENGTH-1)*sizeof(float)); + tput_time_ue[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame; + tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; + if (tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] > tput_ue_max[UE_id]) { + tput_ue_max[UE_id] = tput_ue[UE_id][TPUT_WINDOW_LENGTH-1]; + } + fl_set_xyplot_data(form->pdsch_tput,tput_time_ue[UE_id],tput_ue[UE_id],TPUT_WINDOW_LENGTH,"","",""); + fl_set_xyplot_ybounds(form->pdsch_tput,0,tput_ue_max[UE_id]); + */ + fl_unfreeze_form(form->lte_phy_scope_ue); + fl_check_forms(); + free(I); + free(Q); + free(chest_f_abs); + free(llr0); + free(bit0); + free(llr1); + free(bit1); + free(bit_pdcch); + free(llr_pdcch); + for (arx=0;arx<nb_antennas_rx;arx++) { + free(chest_t_abs[arx]); + } + } diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index 7791306d6d526be5f1197ed46a040bb9063b4f78..233d16ebbea83f7e95acebbbc196dc7c82fffca0 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -45,6 +45,7 @@ typedef struct { long long diff_square; /*!< \brief process duration square */ long long max; int trials; + int meas_flag; } time_stats_t; #elif defined(__arm__) typedef struct { @@ -98,9 +99,14 @@ static inline void start_meas(time_stats_t *ts) { if (opp_enabled) { - + if (ts->meas_flag==0) { ts->trials++; ts->in = rdtsc_oai(); + ts->meas_flag=1; + } + else { + ts->in = rdtsc_oai(); + } } } @@ -120,7 +126,8 @@ static inline void stop_meas(time_stats_t *ts) if ((out-ts->in) > ts->max) ts->max = out-ts->in; - + + ts->meas_flag=0; } } @@ -132,6 +139,7 @@ static inline void reset_meas(time_stats_t *ts) { ts->p_time=0; ts->diff_square=0; ts->max=0; + ts->meas_flag=0; } diff --git a/openair1/PHY/TOOLS/twiddle18432.h b/openair1/PHY/TOOLS/twiddle18432.h index f21987c4cb2b49e201f5d404bbfd9cb15987aeee..8c6c9822dc69c7c15ef1141b40a5ea4454e323bd 100644 --- a/openair1/PHY/TOOLS/twiddle18432.h +++ b/openair1/PHY/TOOLS/twiddle18432.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see <http://www.gnu.org/licenses/>. - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ +/* + * 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.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.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 + */ /* Twiddles generated with twa = floor(32767*exp(-sqrt(-1)*2*pi*(0:6143)/18432)); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 5b1654958eb515cb14f5617e79535935775de485..272051000664a4dc4917c5917e9f90b286df2389 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -32,6 +32,7 @@ #ifndef __PHY_DEFS__H__ #define __PHY_DEFS__H__ +#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <malloc.h> @@ -153,10 +154,10 @@ enum transmission_access_mode { typedef enum { eNodeB_3GPP=0, // classical eNodeB function eNodeB_3GPP_BBU, // eNodeB with NGFI IF5 - NGFI_RCC_IF4p5, // NGFI_RCC (NGFI radio cloud center) + NGFI_RCC_IF4p5, // NGFI_RCC (NGFI radio cloud center) NGFI_RAU_IF4p5, NGFI_RRU_IF5, // NGFI_RRU (NGFI remote radio-unit,IF5) - NGFI_RRU_IF4p5 // NGFI_RRU (NGFI remote radio-unit,IF4p5) + NGFI_RRU_IF4p5 // NGFI_RRU (NGFI remote radio-unit,IF4p5) } eNB_func_t; typedef enum { @@ -391,6 +392,9 @@ typedef struct { pthread_mutex_t mutex_rxtx; /// scheduling parameters for RXn-TXnp4 thread struct sched_param sched_param_rxtx; + int sub_frame_start; + int sub_frame_step; + unsigned long long gotIQs; } UE_rxtx_proc_t; /// Context data structure for eNB subframe processing @@ -592,7 +596,7 @@ typedef struct PHY_VARS_eNB_s { uint32_t total_transmitted_bits; uint32_t total_system_throughput; - int hw_timing_advance; + int hw_timing_advance; time_stats_t phy_proc; time_stats_t phy_proc_tx; @@ -629,7 +633,7 @@ typedef struct PHY_VARS_eNB_s { #ifdef LOCALIZATION /// time state for localization time_stats_t localization_stats; -#endif +#endif int32_t pucch1_stats_cnt[NUMBER_OF_UE_MAX][10]; int32_t pucch1_stats[NUMBER_OF_UE_MAX][10*1024]; @@ -641,9 +645,9 @@ typedef struct PHY_VARS_eNB_s { int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240]; - + /// RF and Interface devices per CC - openair0_device rfdevice; + openair0_device rfdevice; openair0_device ifdevice; /// Pointer for ifdevice buffer struct if_buffer_t ifbuffer; @@ -702,16 +706,16 @@ typedef struct { LTE_DL_FRAME_PARMS frame_parms_before_ho; LTE_UE_COMMON common_vars; - LTE_UE_PDSCH *pdsch_vars[2][NUMBER_OF_CONNECTED_eNB_MAX+1]; + LTE_UE_PDSCH *pdsch_vars[2][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads LTE_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_PDCCH *pdcch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_PDCCH *pdcch_vars[2][NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_DLSCH_t *dlsch[NUMBER_OF_CONNECTED_eNB_MAX][2]; + LTE_UE_DLSCH_t *dlsch[2][NUMBER_OF_CONNECTED_eNB_MAX][2]; // two RxTx Threads LTE_UE_ULSCH_t *ulsch[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; @@ -798,6 +802,8 @@ typedef struct { uint8_t prach_cnt; uint8_t prach_PreambleIndex; // uint8_t prach_timer; + uint8_t decode_SIB; + uint8_t decode_MIB; int rx_offset; /// Timing offset int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP int timing_advance; ///timing advance signalled from eNB @@ -868,7 +874,7 @@ typedef struct { time_stats_t phy_proc; time_stats_t phy_proc_tx; - time_stats_t phy_proc_rx; + time_stats_t phy_proc_rx[2]; uint32_t use_ia_receiver; @@ -881,12 +887,16 @@ typedef struct { time_stats_t ulsch_interleaving_stats; time_stats_t ulsch_multiplexing_stats; + time_stats_t generic_stat; + time_stats_t pdsch_procedures_stat; + time_stats_t dlsch_procedures_stat; + time_stats_t ofdm_demod_stats; time_stats_t dlsch_rx_pdcch_stats; time_stats_t rx_dft_stats; time_stats_t dlsch_channel_estimation_stats; time_stats_t dlsch_freq_offset_estimation_stats; - time_stats_t dlsch_decoding_stats; + time_stats_t dlsch_decoding_stats[2]; time_stats_t dlsch_demodulation_stats; time_stats_t dlsch_rate_unmatching_stats; time_stats_t dlsch_turbo_decoding_stats; @@ -906,7 +916,18 @@ typedef struct { time_stats_t tx_prach; /// RF and Interface devices per CC - openair0_device rfdevice; + openair0_device rfdevice; + time_stats_t dlsch_encoding_SIC_stats; + time_stats_t dlsch_scrambling_SIC_stats; + time_stats_t dlsch_modulation_SIC_stats; + time_stats_t dlsch_llr_stripping_unit_SIC_stats; + time_stats_t dlsch_unscrambling_SIC_stats; + +#if ENABLE_RAL + hash_table_t *ral_thresholds_timed; + SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; + SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; +#endif } PHY_VARS_UE; @@ -919,7 +940,7 @@ static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond, exit_fun("nothing to add"); return(-1); } - + while (*instance_cnt < 0) { // most of the time the thread is waiting here // proc->instance_cnt_rxtx is -1 @@ -941,7 +962,7 @@ static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t * exit_fun("nothing to add"); return(-1); } - + while (*instance_cnt == 0) { // most of the time the thread will skip this // waits only if proc->instance_cnt_rxtx is 0 @@ -963,9 +984,9 @@ static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char * exit_fun("nothing to add"); return(-1); } - + *instance_cnt=*instance_cnt-1; - + if (pthread_mutex_unlock(mutex) != 0) { LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name); exit_fun("nothing to add"); diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h index f6daccfbe0a98bcd43b1dee567d1f3306c669be2..5707aedd27ccdff32b079a7ce142d77522dddd5e 100644 --- a/openair1/PHY/impl_defs_lte.h +++ b/openair1/PHY/impl_defs_lte.h @@ -320,7 +320,7 @@ typedef struct { uint16_t srs_ConfigIndex; /// Parameter: \f$n^\text{CS}_\text{SRS}\f$. See TS 36.211 (5.5.3.1). \vr{[0..7]} \note the specification sais it is an enumerated value. uint8_t cyclicShift; - // Parameter: ue srs subframe for internal implementation + // Parameter: internal implementation: UE SRS configured uint8_t srsConfigDedicatedSetup; // Parameter: cell srs subframe for internal implementation uint8_t srsCellSubframe; @@ -666,8 +666,8 @@ typedef struct { /// - third index: tx antenna [0..nb_antennas_tx[ /// - fourth index: sample [0..] int32_t **beam_weights[3][15]; - /// \brief Holds the tdd reciprocity calibration coefficients - /// - first index: eNB id [0..2] (hard coded) + /// \brief Holds the tdd reciprocity calibration coefficients + /// - first index: eNB id [0..2] (hard coded) /// - second index: tx antenna [0..nb_antennas_tx[ /// - third index: frequency [0..] int32_t **tdd_calib_coeffs[3]; @@ -845,15 +845,22 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **rxdataF_comp0; - /// \brief Received frequency-domain signal after extraction and channel compensation. - /// - first index: ? [0..7] (hard coded) accessed via \c round - /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - third index: ? [0..168*N_RB_DL[ - int32_t **rxdataF_comp1[8]; + /// \brief Received frequency-domain signal after extraction and channel compensation for the second stream. For the SIC receiver we need to store the history of this for each harq process and round + /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid + /// - second index: ? [0..7] (hard coded) accessed via \c round + /// - third index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx + /// - fourth index: ? [0..168*N_RB_DL[ + int32_t **rxdataF_comp1[8][8]; /// \brief Downlink channel estimates extracted in PRBS. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_estimates_ext; + /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. For the SIC receiver we need to store the history of this for each harq process and round + /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid + /// - second index: ? [0..7] (hard coded) accessed via \c round + /// - third index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx + /// - fourth index: ? [0..168*N_RB_DL[ + int32_t **dl_ch_rho_ext[8][8]; /// \brief Downlink beamforming channel estimates in frequency domain. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[ @@ -865,10 +872,6 @@ typedef struct { /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ - int32_t **dl_ch_rho_ext; - /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_rho2_ext; /// \brief Downlink PMIs extracted in PRBS and grouped in subbands. /// - first index: ressource block [0..N_RB_DL[ @@ -880,7 +883,7 @@ typedef struct { /// \brief Magnitude of Downlink Channel second layer (16QAM level/First 64QAM level). /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ - int32_t **dl_ch_mag1; + int32_t **dl_ch_mag1[8][8]; /// \brief Magnitude of Downlink Channel, first layer (2nd 64QAM level). /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ @@ -888,7 +891,7 @@ typedef struct { /// \brief Magnitude of Downlink Channel second layer (2nd 64QAM level). /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ - int32_t **dl_ch_magb1; + int32_t **dl_ch_magb1[8][8]; /// \brief Cross-correlation of two eNB signals. /// - first index: rx antenna [0..nb_antennas_rx[ /// - second index: symbol [0..] @@ -901,6 +904,10 @@ typedef struct { int16_t *llr[2]; /// \f$\log_2(\max|H_i|^2)\f$ int16_t log2_maxh; + /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer1 channel compensation + int16_t log2_maxh0; + /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer2 channel commpensation + int16_t log2_maxh1; /// \brief LLR shifts for subband scaling. /// - first index: ? [0..168*N_RB_DL[ uint8_t *llr_shifts; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index dd09749fbf16bddde06e7b3b7418e87b2ca37ff1..be63ea00cc3a7e5a4d7350651001f642026f33b0 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -202,7 +202,7 @@ #define ONE_OVER_SQRT2_Q15 23170 - +#define ONE_OVER_2_Q15 16384 // QAM amplitude definitions @@ -284,21 +284,7 @@ typedef enum { #define NUMBER_OF_HARQ_PID_MAX 8 #define MAX_FRAME_NUMBER 0x400 -#if defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) -#define NUMBER_OF_eNB_MAX 1 -#define NUMBER_OF_UE_MAX 16 -#define NUMBER_OF_CONNECTED_eNB_MAX 3 -#else -#ifdef LARGE_SCALE -#define NUMBER_OF_eNB_MAX 2 -#define NUMBER_OF_UE_MAX 120 -#define NUMBER_OF_CONNECTED_eNB_MAX 1 // to save some memory -#else -#define NUMBER_OF_eNB_MAX 7 -#define NUMBER_OF_UE_MAX 16 -#define NUMBER_OF_CONNECTED_eNB_MAX 3 -#endif -#endif +#include "openairinterface5g_limits.h" #define NUMBER_OF_RN_MAX 3 typedef enum {no_relay=1,unicast_relay_type1,unicast_relay_type2, multicast_relay} relaying_type_t; diff --git a/openair1/README.TXT b/openair1/README.TXT index 34d3144105dfe8eafef6370d68be93a6f4d97c7f..23c86e888e47f697adb8d1509630d5958e5be693 100644 --- a/openair1/README.TXT +++ b/openair1/README.TXT @@ -1,40 +1,5 @@ This folder contains the software for the device driver of CBMIMO1 and the physical layer signal processing. - -|-- ARCH // contains drivers for hardware -| |-- CBMIMO1 // contains everything related to CBMIMO1 -| | `-- DEVICE_DRIVER -| | |-- Makefile // main Makefile used to compile the driver; usually invoked from the top level Makefile -| | |-- cbmimo1_device.c // main file for device driver (initializes the card, bigphys, main variables) -| | |-- cbmimo1_device.h -| | |-- cbmimo1_dma.c -| | |-- cbmimo1_fileops.c // file that processes IOCTL commands coming from the userspace control utility (USERSPACE_TOOLS/OPENAIR_RF/) -| | |-- cbmimo1_generate_fs4.c // generates test signals (DEBUGGING) -| | |-- cbmimo1_generate_ofdm.c // generates test signals (DEBUGGING) -| | |-- cbmimo1_get_frame.c // code to grab a frame from the card -| | |-- cbmimo1_init.c // code to set up the registers of the card -| | |-- cbmimo1_pci.h -| | |-- cbmimo1_proc.c // generates the proc entries /proc/openair1/bch_stats and /proc/openair1/openair1_state -| | |-- cbmimo1_rf_cntl.c // controls the RF chipset on the card -| | |-- cbmimo1_test.c -| | |-- from_grlib_softconfig.h -| | |-- from_grlib_softregs.h -| | |-- defs.h -| | |-- extern.h -| | `-- vars.h -| |-- COMMON // common for all hardware (mainly bigphys) -| |-- EXPRESS_MIMO // contains everything related to EXPRESS MIMO -|-- DOCS // Documentation -| |-- DOXYGEN // Automaitcally generated DOXYGEN documentation in latex and html -| `-- PAPERS // papers related to openair1 -|-- EMOS // this contains everything related to Eurecom MIMO Openair Sounder (EMOS) -| |-- DOC -| |-- DUMP // program that dumps channel estimate to disk using a FIFO -| |-- GUI -| |-- MATLAB // Matlab code to process measurements -| |-- SIM // EMOS simulator (for DEBUGGING) -| `-- UTIL -|-- MAC_INTERFACE // interface with MAC layer (in openair2) |-- PHY // contains all signal processing related to physical layer (used in real-time AND simulation) General remarks: every directory contains at least defs.h (for declaration of structure and functions), vars.h (for definitions of variables), and extern.h (variables are defined only once in cbmimo1_device.c (for real-time HW operation) or a top-level simulation (in SIMULATION/xxx), if variables are needed in another file, use extern.h) @@ -57,17 +22,19 @@ General remarks: every directory contains at least defs.h (for declaration of st | |-- spec_defs_top.h | |-- types.h | `-- vars.h -|-- SCHED // schedules the different PHY functions according to the nodes role (CH=BS, MR=UE) +|-- SCHED // schedules the different PHY functions according to the nodes role | |-- defs.h | |-- extern.h -| |-- phy_procedures.c // non-LTE PHY procedures this is used in synchronized mode to schedule the slot processing | |-- phy_procedures_emos.c // non-LTE PHY procedures for EMOS | |-- phy_procedures_emos.h | |-- phy_procedures_lte_eNb.c // LTE PHY procedures for eNB (from 36-213) | |-- phy_procedures_lte_ue.c // LTE PHY procedures for UE (from 36-213) +| |-- phy_procedures_lte_common.c // LTE PHY procedures common for UE and eNB (from 36-213) +| |-- phy_mac_stub.c //MAC stub that generates channels when used in phy-test-mode +| |-- pucch_pc.c // power control for PUCCH +| |-- pusch_pc.c // power control for PUSCH +| |-- srs_pc.c // power control for SRS | |-- rt_compat.h -| |-- sched.c // contains the top level scheduler (only for CBMIMO1 HW) -| |-- sched_lte.c // same as sched.c for LTE (only for CBMIMO1 HW) | `-- vars.h |-- SIMULATION // contains simulation routines to test PHY | |-- LTE_PHY // LTE simulation testbenches for unitary simulation of transport/physical channels @@ -76,17 +43,9 @@ General remarks: every directory contains at least defs.h (for declaration of st | | |-- dlsim.c // PDSCH simulation testbench | | |-- ulsim.c // PUSCH simulation testbench | | |-- pucchsim.c // PUCCH simulation testbench -| |-- LTE_PHY_L2 // LTE simulation testbench for full system simulation (PHY,MAC,RLC,RRC,PDCP) -| `-- TOOLS | |-- RF -|-- USERSPACE_TOOLS // tools that run in userspace (not kernel) -| |-- OCTAVE -| | |-- AGILE_RF_TOOLS // octave tools to test agile RF -| | |-- CBMIMO1_TOOLS // octave interface for CBMIMO1 -| | |-- GPIB // octave tools to control signal generator (used for calibration) -| | `-- PHY_SIM // octave implementation of sync -| |-- OPENAIR_RF // tool to interface with the device driver using IOCTL -| |-- SCOPE // tool to visualize data from PHY (channel estimates, IQ plots, etc.). Communicates with kernel module using shared memory. -| `-- SENSING // tools related to sensing +| |-- ETH_TRANSPORT +| `-- TOOLS + diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 5fd5009f1f9c51409b0d04efc89e031caabd7ec4..10d9d69c5219287de740513132754ca1d77cf10d 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -104,7 +104,7 @@ void phy_procedures_eNB_lte(uint8_t subframe,PHY_VARS_eNB **phy_vars_eNB,uint8_t */ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /*! \brief Top-level entry routine for relay node procedures when acting as eNB. This proc will make us of the existing eNB procs. @param last_slot Index of last slot (0-19) @param next_slot Index of next_slot (0-19) @@ -197,7 +197,7 @@ void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,relaying_type_t r_type); */ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type); -/*! \brief Scheduling for eNB PRACH RX procedures +/*! \brief Scheduling for eNB PRACH RX procedures @param phy_vars_eNB Pointer to eNB variables on which to act @param proc Pointer to RXn-TXnp4 proc information */ @@ -212,6 +212,7 @@ void prach_procedures(PHY_VARS_eNB *eNB); lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); + /*! \brief Function to compute which type of DCIs to detect in the given subframe @param frame_parms Pointer to DL frame parameter descriptor @param subframe Subframe index @@ -305,7 +306,7 @@ uint8_t pdcch_alloc2ul_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n); @param o_ACK Pointer to ACK/NAK payload for PUCCH/PUSCH @returns status indicator for PUCCH/PUSCH transmission */ -uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,harq_status_t *harq_ack,uint8_t subframe,uint8_t *o_ACK); +uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,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 @@ -316,8 +317,11 @@ uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,harq_status_t *harq_ack,uint8_t */ uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms, harq_status_t *harq_ack, - unsigned char subframe, - unsigned char *o_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 @@ -509,7 +513,13 @@ int get_ue_active_harq_pid(uint8_t Mod_id,uint8_t CC_id,uint16_t rnti,int frame, void dump_dlsch(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe); void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe); -void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, uint16_t coded_bits_per_codeword,int round); + +void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid); + + +int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx); + +void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset); /*@}*/ diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c index 9a41ae09c52378daf4a514296a3b64bb15afd974..f750253c6787a329aee900c8171778beb45c37a6 100644 --- a/openair1/SCHED/phy_mac_stub.c +++ b/openair1/SCHED/phy_mac_stub.c @@ -70,7 +70,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) uint32_t bcch_pdu; uint64_t dlsch_pdu; - LOG_I(PHY,"frame %d, subframe %d, transmission_mode %d\n",proc->frame_tx,proc->subframe_tx,transmission_mode); + LOG_D(PHY,"frame %d, subframe %d, transmission_mode %d\n",proc->frame_tx,proc->subframe_tx,transmission_mode); DCI_pdu->Num_common_dci = 0; DCI_pdu->Num_ue_spec_dci=0; @@ -380,25 +380,25 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_20MHz_FDD_t; - ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(100,10,3); + harq_pid_value = ( ((proc->frame_tx * 10) + subframe) % 8 ); + + if (!(subframe&1)) // even subframe + dci_ndi_toggle_tmp = &(dci_ndi_toggle_even[harq_pid_value]); + else // odd subframe + dci_ndi_toggle_tmp = &(dci_ndi_toggle_odd[harq_pid_value]); + + ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rballoc = 0x1ffffff; //rballoc; //computeRIV(100,10,3); ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->TPC = 0; - ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->harq_pid = subframe % 5; + ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->harq_pid = harq_pid_value; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->ndi = subframe / 5; + ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->ndi = (*dci_ndi_toggle_tmp); ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rv = 0; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rah = 0; + (*dci_ndi_toggle_tmp) = ((*dci_ndi_toggle_tmp) + 1) & 1; + memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_20MHz_FDD_t)); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = subframe % 5; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = subframe/5; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; - memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); /* //user2 DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1_5MHz_TDD_t; @@ -531,7 +531,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) } } else { - switch (eNB->frame_parms.N_RB_DL==6) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI0_1_5MHz_TDD_1_6_t*)&DCI_pdu->dci_alloc[1].dci_pdu[0])->type = 0; ((DCI0_1_5MHz_TDD_1_6_t*)&DCI_pdu->dci_alloc[1].dci_pdu[0])->hopping = 0; diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c index 93d3c94b1141c6623e1a17059d2be26e55bdaca1..07793413340866a16b5e36ace4ed0f4f08222dda 100644 --- a/openair1/SCHED/phy_procedures_lte_common.c +++ b/openair1/SCHED/phy_procedures_lte_common.c @@ -105,7 +105,47 @@ void get_Msg3_alloc(LTE_DL_FRAME_PARMS *frame_parms, *frame = (current_frame+2) & 1023; break; } - } + } else if (frame_parms->tdd_config == 4) { + switch (current_subframe) { + + case 0: + case 4: + case 5: + case 6: + *subframe = 2; + *frame = (current_frame+1) & 1023; + break; + + case 7: + *subframe = 3; + *frame = (current_frame+1) & 1023; + break; + + case 8: + case 9: + *subframe = 2; + *frame = (current_frame+2) & 1023; + break; + } + } else if (frame_parms->tdd_config == 5) { + switch (current_subframe) { + + case 0: + case 4: + case 5: + case 6: + *subframe = 2; + *frame = (current_frame+1) & 1023; + break; + + case 7: + case 8: + case 9: + *subframe = 2; + *frame = (current_frame+2) & 1023; + break; + } + } } } @@ -137,6 +177,13 @@ void get_Msg3_alloc_ret(LTE_DL_FRAME_PARMS *frame_parms, // original PUSCH in 3, PHICH in 9, ret in 3 next frame // original PUSCH in 4, PHICH in 0, ret in 4 next frame *frame=(current_frame+1) & 1023; + } else if (frame_parms->tdd_config == 4) { + // original PUSCH in 2, PHICH in 8, ret in 2 next frame + // original PUSCH in 3, PHICH in 9, ret in 3 next frame + *frame=(current_frame+1) & 1023; + } else if (frame_parms->tdd_config == 5) { + // original PUSCH in 2, PHICH in 8, ret in 2 next frame + *frame=(current_frame+1) & 1023; } } } @@ -253,6 +300,24 @@ unsigned char ul_ACK_subframe2_dl_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsig break; + case 4: + if (subframe == 2) { // ACK subframes 0, 4 and 5 + //if (ACK_index==2) + // return(1); TBC + if (ACK_index==2) + return(0); + + return(4+ACK_index); + } else if (subframe == 3) { // ACK subframes 6, 7 8 and 9 + return(6+ACK_index); // To be updated + } else { + LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n", + subframe,frame_parms->tdd_config); + return(0); + } + + break; + case 1: if (subframe == 2) { // ACK subframes 5 and 6 return(5+ACK_index); @@ -297,6 +362,30 @@ unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char s break; + case 4: + if (subframe == 2) { // ACK subframes 0,4 and 5 + return(3); // should be 4 + } else if (subframe == 3) { // ACK subframes 6,7,8 and 9 + return(4); + } else { + LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n", + subframe,frame_parms->tdd_config); + return(0); + } + + break; + + case 5: + if (subframe == 2) { // ACK subframes 0,3,4,5,6,7,8 and 9 + return(8); // should be 3 + } else { + LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n", + subframe,frame_parms->tdd_config); + return(0); + } + + break; + case 1: if (subframe == 2) { // ACK subframes 5 and 6 return(2); @@ -323,69 +412,73 @@ unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char s // return the number 'Nbundled' uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms, harq_status_t *harq_ack, - unsigned char subframe, + unsigned char subframe_tx, + unsigned char subframe_rx, unsigned char *o_ACK, + uint8_t *pN_bundled, + uint8_t cw_idx, uint8_t do_reset) // 1 to reset ACK/NACK status : 0 otherwise { uint8_t status=0; - uint8_t subframe_ul=0xff, subframe_dl0=0xff, subframe_dl1=0xff; + uint8_t subframe_ul=0xff, subframe_dl0=0xff, subframe_dl1=0xff,subframe_dl2=0xff, subframe_dl3=0xff; // printf("get_ack: SF %d\n",subframe); if (frame_parms->frame_type == FDD) { - if (subframe < 4) - subframe_dl0 = subframe + 6; + if (subframe_tx < 4) + subframe_dl0 = subframe_tx + 6; else - subframe_dl0 = subframe - 4; + subframe_dl0 = subframe_tx - 4; - o_ACK[0] = harq_ack[subframe_dl0].ack; + o_ACK[cw_idx] = harq_ack[subframe_dl0].ack; status = harq_ack[subframe_dl0].send_harq_status; + //LOG_I(PHY,"dl subframe %d send_harq_status %d cw_idx %d, reset %d\n",subframe_dl0, status, cw_idx, do_reset); if(do_reset) harq_ack[subframe_dl0].send_harq_status = 0; //printf("get_ack: Getting ACK/NAK for PDSCH (subframe %d) => %d\n",subframe_dl,o_ACK[0]); } else { switch (frame_parms->tdd_config) { case 1: - if (subframe == 2) { // ACK subframes 5,6 + if (subframe_tx == 2) { // ACK subframes 5,6 subframe_ul = 6; subframe_dl0 = 5; subframe_dl1 = 6; - } else if (subframe == 3) { // ACK subframe 9 + } else if (subframe_tx == 3) { // ACK subframe 9 subframe_ul = 9; subframe_dl0 = 9; subframe_dl1 = 0xff; - } else if (subframe == 4) { // nothing + } else if (subframe_tx == 4) { // nothing subframe_ul = 0xff; subframe_dl0 = 0xff; // invalid subframe number indicates ACK/NACK is not needed subframe_dl1 = 0xff; - } else if (subframe == 7) { // ACK subframes 0,1 + } else if (subframe_tx == 7) { // ACK subframes 0,1 subframe_ul = 1; subframe_dl0 = 0; subframe_dl1 = 1; - } else if (subframe == 8) { // ACK subframes 4 + } else if (subframe_tx == 8) { // ACK subframes 4 subframe_ul = 4; subframe_dl0 = 4; subframe_dl1 = 0xff; } else { - LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe %d for tdd_config %d\n", - subframe,frame_parms->tdd_config); + LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n", + subframe_tx,frame_parms->tdd_config); return(0); } // report ACK/NACK status - o_ACK[0] = 1; + o_ACK[cw_idx] = 1; status = 0; if ((subframe_dl0 < 10) && (harq_ack[subframe_dl0].send_harq_status)) { - o_ACK[0] &= harq_ack[subframe_dl0].ack; + o_ACK[cw_idx] &= harq_ack[subframe_dl0].ack; status = harq_ack[subframe_dl0].send_harq_status; } if ((subframe_dl1 < 10) && (harq_ack[subframe_dl1].send_harq_status)) { - o_ACK[0] &= harq_ack[subframe_dl1].ack; + o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack; status = harq_ack[subframe_dl1].send_harq_status; } // report status = Nbundled if (!status) { - o_ACK[0] = 0; + o_ACK[cw_idx] = 0; } else { if (harq_ack[subframe_ul].vDAI_UL < 0xff) { status = harq_ack[subframe_ul].vDAI_UL; @@ -395,26 +488,26 @@ uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms, if (!do_reset && (subframe_ul < 10)) { if ((subframe_dl0 < 10) && (subframe_dl1 < 10)) { LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n", - subframe, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status, + subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status, subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL, subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL, - o_ACK[0], status); + o_ACK[cw_idx], status); } else if (subframe_dl0 < 10) { LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n", - subframe, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status, + subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status, subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL, - o_ACK[0], status); + o_ACK[cw_idx], status); }else if (subframe_dl1 < 10) { LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n", - subframe, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status, + subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status, subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL, - o_ACK[0], status); + o_ACK[cw_idx], status); } } // reset ACK/NACK status if (do_reset) { - LOG_D(PHY,"ul-sf#%d ACK/NACK status resetting @ dci0-sf#%d, dci1x/2x-sf#%d, dci1x/2x-sf#%d\n", subframe, subframe_ul, subframe_dl0, subframe_dl1); + LOG_D(PHY,"ul-sf#%d ACK/NACK status resetting @ dci0-sf#%d, dci1x/2x-sf#%d, dci1x/2x-sf#%d\n", subframe_tx, subframe_ul, subframe_dl0, subframe_dl1); if (subframe_ul < 10) { harq_ack[subframe_ul].vDAI_UL = 0xff; } @@ -433,36 +526,44 @@ uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms, break; case 3: - if (subframe == 2) { // ACK subframes 5 and 6 + if (subframe_tx == 2) { // ACK subframes 5 and 6 subframe_dl0 = 5; subframe_dl1 = 6; - //printf("Subframe 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status); - } else if (subframe == 3) { // ACK subframes 7 and 8 + subframe_ul = 2; + //printf("subframe_tx 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status); + } else if (subframe_tx == 3) { // ACK subframes 7 and 8 subframe_dl0 = 7; subframe_dl1 = 8; + subframe_ul = 3; //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack); //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]); - } else if (subframe == 4) { // ACK subframes 9 and 0 + } else if (subframe_tx == 4) { // ACK subframes 9 and 0 subframe_dl0 = 9; subframe_dl1 = 0; + subframe_ul = 4; //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack); } else { - LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe %d for tdd_config %d\n", - subframe,frame_parms->tdd_config); + LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n", + subframe_tx,frame_parms->tdd_config); return(0); } // report ACK/NACK status + o_ACK[cw_idx] = 0; if (harq_ack[subframe_dl0].send_harq_status == 1) { - o_ACK[0] = harq_ack[subframe_dl0].ack; + o_ACK[cw_idx] = harq_ack[subframe_dl0].ack; if (harq_ack[subframe_dl1].send_harq_status == 1) - o_ACK[1] = harq_ack[subframe_dl1].ack; + o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack; } else if (harq_ack[subframe_dl1].send_harq_status == 1) - o_ACK[0] = harq_ack[subframe_dl1].ack; + o_ACK[cw_idx] = harq_ack[subframe_dl1].ack; - status = harq_ack[subframe_dl0].send_harq_status + (harq_ack[subframe_dl1].send_harq_status<<1); + pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL; + status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status; + //LOG_D(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d subframe_rx %d N_bundled %d \n", + // subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack, + // subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack, subframe_rx, pN_bundled[0]); if (do_reset) { // reset ACK/NACK status harq_ack[subframe_dl0].ack = 2; @@ -473,6 +574,63 @@ uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms, break; + case 4: + if (subframe_tx == 2) { // ACK subframes 4, 5 and 0 + subframe_dl0 = 4; + subframe_dl1 = 5; + subframe_dl2 = 0; + subframe_ul = 2; + //printf("subframe_tx 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status); + } else if (subframe_tx == 3) { // ACK subframes 6, 7 8 and 9 + subframe_dl0 = 6; + subframe_dl1 = 7; + subframe_dl2 = 8; + subframe_dl3 = 9; + subframe_ul = 3; + //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack); + //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]); + } else { + LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n", + subframe_tx,frame_parms->tdd_config); + return(0); + } + + // report ACK/NACK status + o_ACK[cw_idx] = 0; + if (harq_ack[subframe_dl0].send_harq_status == 1) + o_ACK[cw_idx] = harq_ack[subframe_dl0].ack; + + if (harq_ack[subframe_dl1].send_harq_status == 1) + o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack; + + if (harq_ack[subframe_dl2].send_harq_status == 1) + o_ACK[cw_idx] &= harq_ack[subframe_dl2].ack; + + if (harq_ack[subframe_dl3].send_harq_status == 1) + o_ACK[cw_idx] &= harq_ack[subframe_dl3].ack; + + pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL; + status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status + harq_ack[subframe_dl2].send_harq_status + harq_ack[subframe_dl3].send_harq_status; + + LOG_I(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d dl Sfn2 %d status %d o_Ack %d dl Sfn3 %d status %d o_Ack %d subframe_rx %d N_bundled %d status %d\n", + subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack, + subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack, + subframe_dl2, harq_ack[subframe_dl2].send_harq_status,harq_ack[subframe_dl2].ack, + subframe_dl3, harq_ack[subframe_dl3].send_harq_status,harq_ack[subframe_dl3].ack,subframe_rx, pN_bundled[0], status); + if (do_reset) { + // reset ACK/NACK status + harq_ack[subframe_dl0].ack = 2; + harq_ack[subframe_dl1].ack = 2; + harq_ack[subframe_dl2].ack = 2; + harq_ack[subframe_dl3].ack = 2; + harq_ack[subframe_dl0].send_harq_status = 0; + harq_ack[subframe_dl1].send_harq_status = 0; + harq_ack[subframe_dl2].send_harq_status = 0; + harq_ack[subframe_dl3].send_harq_status = 0; + } + + break; + } } @@ -483,18 +641,24 @@ uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms, uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms, harq_status_t *harq_ack, - unsigned char subframe, - unsigned char *o_ACK) + unsigned char subframe_tx, + unsigned char subframe_rx, + unsigned char *o_ACK, + uint8_t cw_idx) { - return get_reset_ack(frame_parms, harq_ack, subframe, o_ACK, 0); + uint8_t N_bundled = 0; + return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, &N_bundled, cw_idx, 0); } uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms, harq_status_t *harq_ack, - unsigned char subframe, - unsigned char *o_ACK) + unsigned char subframe_tx, + unsigned char subframe_rx, + unsigned char *o_ACK, + uint8_t *pN_bundled, + uint8_t cw_idx) { - return get_reset_ack(frame_parms, harq_ack, subframe, o_ACK, 1); + return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, pN_bundled, cw_idx, 1); } @@ -591,6 +755,29 @@ lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,unsigned char sub return(255); } + case 4: + if ((subframe<1) || (subframe>=4)) + return(SF_DL); + else if ((subframe>1) && (subframe < 4)) + return(SF_UL); + else if (subframe==1) + return (SF_S); + else { + LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n"); + return(255); + } + + case 5: + if ((subframe<1) || (subframe>=3)) + return(SF_DL); + else if ((subframe>1) && (subframe < 3)) + return(SF_UL); + else if (subframe==1) + return (SF_S); + else { + LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n"); + return(255); + } break; default: @@ -665,13 +852,13 @@ unsigned int is_phich_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char sub break; case 4: - if ((subframe == 0) || (subframe == 8) ) + if ((subframe == 8) || (subframe == 9) ) return(1); break; case 5: - if (subframe == 0) + if (subframe == 8) return(1); break; @@ -939,3 +1126,148 @@ MU_MIMO_mode *get_mu_mimo_mode (module_id_t Mod_id, uint8_t CC_id, rnti_t rnti) return &PHY_vars_eNB_g[Mod_id][CC_id]->mu_mimo_mode[UE_id]; } + +int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx) +{ + uint8_t isSubframeSRS = 0; // SRS Cell Occasion + + //ue->ulsch[eNB_id]->srs_active = 0; + //ue->ulsch[eNB_id]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active; + if(frame_parms->soundingrs_ul_config_common.enabled_flag) + { + + LOG_D(PHY," SRS SUBFRAMECONFIG: %d\n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig); + + uint8_t TSFC; + uint16_t deltaTSFC; // bitmap + uint8_t srs_SubframeConfig; + + // table resuming TSFC (Period) and deltaSFC (offset) + const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD + const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD + + srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig; + if (FDD == frame_parms->frame_type) + { + // srs_SubframeConfig =< 14 + deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0]; + TSFC = deltaTSFCTabType1[srs_SubframeConfig][1]; + } + else + { + // srs_SubframeConfig =< 13 + deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0]; + TSFC = deltaTSFCTabType2[srs_SubframeConfig][1]; + } + + // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC + uint16_t tmp = (subframe_tx % TSFC); + if((1<<tmp) & deltaTSFC) + { + // This is a Sounding reference signal subframes + isSubframeSRS = 1; + } + LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d\n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx); + } + return(isSubframeSRS); +} + +void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset) +{ + if(TDD == frameType) + { + if(isrs<10) + { + mac_xface->macphy_exit("2 ms SRS periodicity not supported"); + } + + if((isrs>9)&&(isrs<15)) + { + *psrsPeriodicity=5; + *psrsOffset=isrs-10; + } + if((isrs>14)&&(isrs<25)) + { + *psrsPeriodicity=10; + *psrsOffset=isrs-15; + } + if((isrs>24)&&(isrs<45)) + { + *psrsPeriodicity=20; + *psrsOffset=isrs-25; + } + if((isrs>44)&&(isrs<85)) + { + *psrsPeriodicity=40; + *psrsOffset=isrs-45; + } + if((isrs>84)&&(isrs<165)) + { + *psrsPeriodicity=80; + *psrsOffset=isrs-85; + } + if((isrs>164)&&(isrs<325)) + { + *psrsPeriodicity=160; + *psrsOffset=isrs-165; + } + if((isrs>324)&&(isrs<645)) + { + *psrsPeriodicity=320; + *psrsOffset=isrs-325; + } + + if(isrs>644) + { + mac_xface->macphy_exit("Isrs out of range"); + } + + } + else + { + if(isrs<2) + { + *psrsPeriodicity=2; + *psrsOffset=isrs; + } + if((isrs>1)&&(isrs<7)) + { + *psrsPeriodicity=5; + *psrsOffset=isrs-2; + } + if((isrs>6)&&(isrs<17)) + { + *psrsPeriodicity=10; + *psrsOffset=isrs-7; + } + if((isrs>16)&&(isrs<37)) + { + *psrsPeriodicity=20; + *psrsOffset=isrs-17; + } + if((isrs>36)&&(isrs<77)) + { + *psrsPeriodicity=40; + *psrsOffset=isrs-37; + } + if((isrs>76)&&(isrs<157)) + { + *psrsPeriodicity=80; + *psrsOffset=isrs-77; + } + if((isrs>156)&&(isrs<317)) + { + *psrsPeriodicity=160; + *psrsOffset=isrs-157; + } + if((isrs>316)&&(isrs<637)) + { + *psrsPeriodicity=320; + *psrsOffset=isrs-317; + } + if(isrs>636) + { + mac_xface->macphy_exit("Isrs out of range"); + } + } +} diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 5b49abbe217961b705bd2e0046ae6e2d829546eb..f8b9a9ae5965be7f4fd4fee20623e0a168ac7e4b 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -78,7 +78,8 @@ void exit_fun(const char* s); extern int exit_openair; - +struct timespec start_fh, start_fh_prev; +int start_fh_sf, start_fh_prev_sf; // Fix per CC openair rf/if device update // extern openair0_device openair0; @@ -189,7 +190,7 @@ int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { eNB = PHY_vars_eNB_g[Mod_idP][CC_id]; for (i=0; i<NUMBER_OF_UE_MAX; i++) { if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) { - MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (ENOMEM)", rnti); + MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (ENOMEM)", rntiP); LOG_E(PHY,"Can't remove UE, not enough memory allocated\n"); return(-1); } else { @@ -306,8 +307,6 @@ void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB) } #endif - - void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type) { UNUSED(r_type); @@ -408,7 +407,7 @@ DCI_PDU DCI_pdu_tmp; void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) { -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) MCH_PDU *mch_pduP; MCH_PDU mch_pdu; // uint8_t sync_area=255; @@ -424,7 +423,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,rel subframe<<1,1); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // if mcch is active, send regardless of the node type: eNB or RN // when mcch is active, MAC sched does not allow MCCH and MTCH multiplexing mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id, @@ -689,7 +688,7 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC dci_alloc->format, &eNB->dlsch_SI, fp, - eNB->pdsch_config_dedicated, + NULL, SI_RNTI, 0, P_RNTI, @@ -723,7 +722,7 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC dci_alloc->format, &eNB->dlsch_ra, fp, - eNB->pdsch_config_dedicated, + NULL, SI_RNTI, dci_alloc->rnti, P_RNTI, @@ -773,7 +772,7 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC dci_alloc->format, eNB->dlsch[(uint8_t)UE_id], fp, - eNB->pdsch_config_dedicated, + &eNB->pdsch_config_dedicated[UE_id], SI_RNTI, 0, P_RNTI, @@ -823,6 +822,13 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int frame = proc->frame_tx; int subframe = proc->subframe_tx; + /* + uint16_t srsPeriodicity=0; + uint16_t srsOffset=0; + uint16_t srsConfigIndex=0; + uint16_t do_srs=0; + */ + uint16_t is_srs_pos=0; LOG_D(PHY, "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n", @@ -838,6 +844,20 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC dci_alloc->dci_pdu[0], 1<<dci_alloc->L); + is_srs_pos = is_srs_occasion_common(fp,pdcch_alloc2ul_frame(fp,frame,subframe),pdcch_alloc2ul_subframe(fp,subframe)); + /* + if (is_srs_pos && eNB->soundingrs_ul_config_dedicated[UE_id].srsConfigDedicatedSetup) { + srsConfigIndex = eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex; + compute_srs_pos(fp->frame_type, srsConfigIndex, &srsPeriodicity, &srsOffset); + if ((((10*pdcch_alloc2ul_frame(fp,frame,subframe)+pdcch_alloc2ul_subframe(fp,subframe)) % srsPeriodicity) == srsOffset)) { + do_srs = 1; + } + } + LOG_D(PHY,"frame %d (%d), subframe %d (%d), UE_id %d: is_srs_pos %d, do_SRS %d, index %d, period %d, offset %d \n", + frame,pdcch_alloc2ul_frame(fp,frame,subframe),subframe,pdcch_alloc2ul_subframe(fp,subframe), + UE_id,is_srs_pos,do_srs,srsConfigIndex,srsPeriodicity,srsOffset); + */ + generate_eNB_ulsch_params_from_dci(eNB, proc, &dci_alloc->dci_pdu[0], @@ -848,7 +868,7 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC 0, P_RNTI, CBA_RNTI, - 0); // do_srs + is_srs_pos); LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d\n", eNB->Mod_id,frame,subframe,dci_alloc->rnti, @@ -886,7 +906,9 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->round), T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->first_rb), T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->nb_rb), - T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->TBS)); + T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->TBS), + T_INT(dci_alloc->L), + T_INT(dci_alloc->firstCCE)); } void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols) { @@ -898,7 +920,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d int input_buffer_length = dlsch_harq->TBS/8; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t *DLSCH_pdu=NULL; - uint8_t DLSCH_pdu_tmp[768*8]; + uint8_t DLSCH_pdu_tmp[input_buffer_length+4]; //[768*8]; uint8_t DLSCH_pdu_rar[256]; int i; @@ -988,17 +1010,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d generate_eNB_ulsch_params_from_rar(DLSCH_pdu, frame, - (subframe), + subframe, eNB->ulsch[(uint32_t)UE_id], fp); - eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1; - - get_Msg3_alloc(fp, - subframe, - frame, - &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, - &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n", frame, subframe, @@ -1343,7 +1358,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, // Apply physicalConfigDedicated if needed // This is for UEs that have received this IE, which changes these DL and UL configuration, we apply after a delay for the eNodeB UL parameters phy_config_dedicated_eNB_step2(eNB); - + // Now loop again over the DCIs for UL configuration for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) { dci_alloc = &DCI_pdu->dci_alloc[i]; @@ -1480,7 +1495,13 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, 0); } - + /* + if (frame>=10 && subframe>=9) { + write_output("/tmp/txsigF0.m","txsF0", &eNB->common_vars.txdataF[0][0][0],120*eNB->frame_parms.ofdm_symbol_size,1,1); + write_output("/tmp/txsigF1.m","txsF1", &eNB->common_vars.txdataF[0][0][0],120*eNB->frame_parms.ofdm_symbol_size,1,1); + abort(); + } + */ #ifdef EMOS phy_procedures_emos_eNB_TX(subframe, eNB); @@ -2064,7 +2085,7 @@ void prach_procedures(PHY_VARS_eNB *eNB) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } -void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) +void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,uint8_t do_srs) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0}; @@ -2143,7 +2164,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq UE_id, eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, 0, // n2_pucch - 0, // shortened format, should be use_srs flag, later + do_srs, // shortened format &SR_payload, frame, subframe, @@ -2183,7 +2204,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq UE_id, (uint16_t)n1_pucch0, 0, //n2_pucch - 0, // shortened format + do_srs, // shortened format pucch_payload0, frame, subframe, @@ -2213,7 +2234,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq UE_id, eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, 0, //n2_pucch - 0, // shortened format + do_srs, // shortened format pucch_payload0, frame, subframe, @@ -2253,7 +2274,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq if ((fp->frame_type==FDD) || (bundling_flag==bundling) || - ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)||(subframe!=7)))) { + ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)&&(subframe!=7)))) { format = pucch_format1a; } else { format = pucch_format1b; @@ -2274,7 +2295,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq UE_id, eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, 0, //n2_pucch - 0, // shortened format + do_srs, // shortened format pucch_payload0, frame, subframe, @@ -2306,7 +2327,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq UE_id, (uint16_t)n1_pucch0, 0, // n2_pucch - 0, // shortened format + do_srs, // shortened format pucch_payload0, frame, subframe, @@ -2331,7 +2352,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq UE_id, (uint16_t)n1_pucch1, 0, //n2_pucch - 0, // shortened format + do_srs, // shortened format pucch_payload1, frame, subframe, @@ -2597,6 +2618,7 @@ extern int oai_exit; static void *fep_thread(void *param) { + pthread_setname_np( pthread_self(), "UEfep"); PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; eNB_proc_t *proc = &eNB->proc; while (!oai_exit) { @@ -2744,6 +2766,10 @@ void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// LOG_D(PHY,"send_IF4p5 (PULFFT): frame %d, subframe %d\n",proc_rxtx->frame_rx,proc_rxtx->subframe_rx); send_IF4p5(eNB, proc_rxtx->frame_rx, proc_rxtx->subframe_rx, IF4p5_PULFFT, 0); + start_fh_prev = start_fh; + start_fh_prev_sf = start_fh_sf; + clock_gettime( CLOCK_MONOTONIC, &start_fh); + start_fh_sf = proc_rxtx->subframe_rx; } } @@ -2755,6 +2781,10 @@ void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) { /// **** send_IF5 of rxdata to BBU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); + start_fh_prev = start_fh; + start_fh_prev_sf = start_fh_sf; + clock_gettime( CLOCK_MONOTONIC, &start_fh); + start_fh_sf = proc->subframe_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); } @@ -2850,6 +2880,16 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const const int frame = proc->frame_rx; int offset = eNB->CC_id;//(proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; + uint16_t srsPeriodicity; + uint16_t srsOffset; + uint16_t do_srs=0; + uint16_t is_srs_pos=0; + + T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe)); + + T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0), + T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti], + eNB->frame_parms.samples_per_tti * 4)); if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; @@ -2859,19 +2899,12 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe); #endif - T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe)); - - T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0), - T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti], - eNB->frame_parms.samples_per_tti * 4)); eNB->rb_mask_ul[0]=0; eNB->rb_mask_ul[1]=0; eNB->rb_mask_ul[2]=0; eNB->rb_mask_ul[3]=0; - - // Check for active processes in current subframe harq_pid = subframe2harq_pid(fp, frame,subframe); @@ -2881,13 +2914,36 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const eNB->cba_last_reception[i]=0; } - // Do PUCCH processing first - + is_srs_pos = is_srs_occasion_common(fp,frame,subframe); + for (i=0; i<NUMBER_OF_UE_MAX; i++) { - pucch_procedures(eNB,proc,i,harq_pid); - } - for (i=0; i<NUMBER_OF_UE_MAX; i++) { + // Do SRS processing + // check if there is SRS and we have to use shortened format + // TODO: check for exceptions in transmission of SRS together with ACK/NACK + do_srs=0; + if (is_srs_pos && eNB->soundingrs_ul_config_dedicated[i].srsConfigDedicatedSetup ) { + compute_srs_pos(fp->frame_type, eNB->soundingrs_ul_config_dedicated[i].srs_ConfigIndex, &srsPeriodicity, &srsOffset); + if (((10*frame+subframe) % srsPeriodicity) == srsOffset) { + do_srs = 1; + } + } + + if (do_srs==1) { + if (lte_srs_channel_estimation(fp, + &eNB->common_vars, + &eNB->srs_vars[i], + &eNB->soundingrs_ul_config_dedicated[i], + subframe, + 0/*eNB_id*/)) { + LOG_E(PHY,"problem processing SRS\n"); + } + } + + // Do PUCCH processing + + pucch_procedures(eNB,proc,i,harq_pid, do_srs); + // check for Msg3 if (eNB->mac_enabled==1) { @@ -3445,7 +3501,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const #undef DEBUG_PHY_PROC -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type) { @@ -3473,3 +3529,4 @@ int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, r return do_proc; } #endif + diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index e061effadb44f487baea3e8e2f5c4458b26f7dea..d3d763cd56d84951cc444bae8486cb6cf71d53cb 100644 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -75,6 +75,7 @@ fifo_dump_emos_UE emos_dump_UE; extern int oai_exit; +extern double cpuf; @@ -90,11 +91,11 @@ void dump_dlsch(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subf uint8_t nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; coded_bits_per_codeword = get_G(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->nb_rb, + ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->Qm, + ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols, proc->frame_rx, subframe, ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); @@ -125,7 +126,7 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, 2, 1, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols, proc->frame_rx, subframe, 0); @@ -136,7 +137,7 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s 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[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols, coded_bits_per_codeword); write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1); @@ -230,7 +231,7 @@ void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, 2, 1, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols, proc->frame_rx, subframe, 0); @@ -239,7 +240,7 @@ void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s 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[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols, coded_bits_per_codeword); write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0],2*12*ue->frame_parms.ofdm_symbol_size,2,1); @@ -258,7 +259,6 @@ void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s 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) { @@ -268,37 +268,39 @@ void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) uint8_t i,j,k,s; PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - //[NUMBER_OF_CONNECTED_eNB_MAX][2]; - for(i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { - for(j=0; j<2; j++) { - //DL HARQ - if(ue->dlsch[i][j]) { - for(k=0; k<NUMBER_OF_HARQ_PID_MAX && ue->dlsch[i][j]->harq_processes[k]; k++) { - ue->dlsch[i][j]->harq_processes[k]->status = SCH_IDLE; - for (s=0; s<10; s++) { - // reset ACK/NACK bit to DTX for all subframes s = 0..9 - ue->dlsch[i][j]->harq_ack[s].ack = 2; - ue->dlsch[i][j]->harq_ack[s].send_harq_status = 0; - ue->dlsch[i][j]->harq_ack[s].vDAI_UL = 0xff; - ue->dlsch[i][j]->harq_ack[s].vDAI_DL = 0xff; + //[NUMBER_OF_RX_THREAD=2][NUMBER_OF_CONNECTED_eNB_MAX][2]; + for(int l=0; l<2; 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 subframes 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; + //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; + // flush Msg3 buffer + ue->ulsch_Msg3_active[i] = 0; + } } } @@ -307,8 +309,10 @@ 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[eNB_index]->crnti_is_temporary = 0; - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[eNB_index]->crnti = 0; + 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(""); } @@ -320,14 +324,16 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) 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[eNB_index]->crnti_is_temporary = 0; + 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[eNB_index][0]->harq_processes[i]->round=0; + 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; } } @@ -364,7 +370,7 @@ void process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance) 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_I(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); + 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); } @@ -375,7 +381,7 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) int subframe=proc->subframe_tx; LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Checking for SR TXOp (sr_ConfigIndex %d)\n", - ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,proc->frame_tx,subframe, + ue->Mod_id,ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->crnti,proc->frame_tx,subframe, ue->scheduling_request_config[eNB_id].sr_ConfigIndex); if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) { // 5 ms SR period @@ -409,7 +415,9 @@ uint8_t is_cqi_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) // cqirep->cqi_PMI_ConfigIndex, // (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)); - if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI) + if (cqirep->cqi_PMI_ConfigIndex==-1) + return(0); + else if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI) return(1); else return(0); @@ -428,170 +436,52 @@ uint8_t is_ri_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe, // cqirep->ri_ConfigIndex, // (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)); - - if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0) + if (cqirep->ri_ConfigIndex==-1) + return(0); + else if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0) return(1); else return(0); } -void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset) +void compute_cqi_ri_resources(PHY_VARS_UE *ue, + LTE_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) { - if(TDD == frameType) - { - if(isrs<10) - { - mac_xface->macphy_exit("2 ms SRS periodicity not supported"); - } + //PHY_MEASUREMENTS *meas = &ue->measurements; + //uint8_t transmission_mode = ue->transmission_mode[eNB_id]; - if((isrs>9)&&(isrs<15)) - { - *psrsPeriodicity=5; - *psrsOffset=isrs-10; - } - if((isrs>14)&&(isrs<25)) - { - *psrsPeriodicity=10; - *psrsOffset=isrs-15; - } - if((isrs>24)&&(isrs<45)) - { - *psrsPeriodicity=20; - *psrsOffset=isrs-25; - } - if((isrs>44)&&(isrs<85)) - { - *psrsPeriodicity=40; - *psrsOffset=isrs-45; - } - if((isrs>84)&&(isrs<165)) - { - *psrsPeriodicity=80; - *psrsOffset=isrs-85; - } - if((isrs>164)&&(isrs<325)) - { - *psrsPeriodicity=160; - *psrsOffset=isrs-165; - } - if((isrs>324)&&(isrs<645)) - { - *psrsPeriodicity=320; - *psrsOffset=isrs-325; - } - - if(isrs>644) - { - mac_xface->macphy_exit("Isrs out of range"); - } - } - else + //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) { - if(isrs<2) - { - *psrsPeriodicity=2; - *psrsOffset=isrs; - } - if((isrs>1)&&(isrs<7)) - { - *psrsPeriodicity=5; - *psrsOffset=isrs-2; - } - if((isrs>6)&&(isrs<17)) - { - *psrsPeriodicity=10; - *psrsOffset=isrs-7; - } - if((isrs>16)&&(isrs<37)) - { - *psrsPeriodicity=20; - *psrsOffset=isrs-17; - } - if((isrs>36)&&(isrs<77)) - { - *psrsPeriodicity=40; - *psrsOffset=isrs-37; - } - if((isrs>76)&&(isrs<157)) - { - *psrsPeriodicity=80; - *psrsOffset=isrs-77; - } - if((isrs>156)&&(isrs<317)) - { - *psrsPeriodicity=160; - *psrsOffset=isrs-157; - } - if((isrs>316)&&(isrs<637)) - { - *psrsPeriodicity=320; - *psrsOffset=isrs-317; - } - if(isrs>636) - { - mac_xface->macphy_exit("Isrs out of range"); - } + ulsch->O = 4; } } -void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) +void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t isSubframeSRS) { - LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - int frame_tx = proc->frame_tx; - int subframe_tx = proc->subframe_tx; - uint8_t isSubframeSRS = 0; // SRS Cell Occasion - - uint8_t is_pucch2_subframe = 0; - uint8_t is_sr_an_subframe = 0; - - SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; + + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int frame_tx = proc->frame_tx; + int subframe_tx = proc->subframe_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 = 0; - - ue->ulsch[eNB_id]->srs_active = 0; - ue->ulsch[eNB_id]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active; - if(frame_parms->soundingrs_ul_config_common.enabled_flag) - { - - LOG_D(PHY," SRS SUBFRAMECONFIG: %d, Isrs: %d \n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig, pSoundingrs_ul_config_dedicated->srs_ConfigIndex); - - uint8_t TSFC; - uint16_t deltaTSFC; // bitmap - uint8_t srs_SubframeConfig; - uint16_t srsPeriodicity; - uint16_t srsOffset; + pSoundingrs_ul_config_dedicated->srsCellSubframe = isSubframeSRS; - // table resuming TSFC (Period) and deltaSFC (offset) - const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD - const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD - - srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig; - if (FDD == frame_parms->frame_type) - { - // srs_SubframeConfig =< 14 - deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0]; - TSFC = deltaTSFCTabType1[srs_SubframeConfig][1]; - } - else - { - // srs_SubframeConfig =< 13 - deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0]; - TSFC = deltaTSFCTabType2[srs_SubframeConfig][1]; - } - - // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC - uint16_t tmp = (subframe_tx % TSFC); - if((1<<tmp) & deltaTSFC) - { - // This is a Sounding reference signal subframes - isSubframeSRS = 1; - pSoundingrs_ul_config_dedicated->srsCellSubframe = 1; - } - LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d, srsCellSubframe: %d \n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx, pSoundingrs_ul_config_dedicated->srsCellSubframe); - LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup); + if (isSubframeSRS) { + LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup); if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup) { compute_srs_pos(frame_parms->frame_type, pSoundingrs_ul_config_dedicated->srs_ConfigIndex, &srsPeriodicity, &srsOffset); @@ -628,7 +518,7 @@ void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id CC_id, frame_tx, eNB_id, - ue->pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->crnti, subframe_tx); // subframe used for meas gap if (SR_payload > 0) @@ -638,8 +528,8 @@ void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id uint8_t pucch_ack_payload[2]; if (get_ack(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_ack, - subframe_tx,pucch_ack_payload) > 0) + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack, + subframe_tx,proc->subframe_rx,pucch_ack_payload,0) > 0) { is_sr_an_subframe = 1; } @@ -666,6 +556,7 @@ void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id } } + void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id) { @@ -737,6 +628,69 @@ void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id) } } +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) +{ + 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) + { + return pucch_format1a; + } + 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 get_n1_pucch(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, harq_status_t *harq_ack, @@ -746,13 +700,14 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, { LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - uint8_t nCCE0,nCCE1,harq_ack1,harq_ack0; + 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; + 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 subframe=proc->subframe_tx; @@ -760,10 +715,10 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, if (frame_parms->frame_type == FDD ) { // FDD sf = (subframe<4)? subframe+6 : subframe-4; - LOG_D(PHY,"n1_pucch_UE: subframe %d, nCCE %d\n",sf,ue->pdcch_vars[eNB_id]->nCCE[sf]); + LOG_D(PHY,"n1_pucch_UE: subframe %d, nCCE %d\n",sf,ue->pdcch_vars[proc->subframe_rx&0x1][eNB_id]->nCCE[sf]); if (SR == 0) - return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[eNB_id]->nCCE[sf]); + return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[sf]); else return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } else { @@ -772,10 +727,10 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, #ifdef DEBUG_PHY_PROC if (bundling_flag==bundling) { - LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR, + LOG_I(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR, ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } else { - LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR, + LOG_I(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR, ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } @@ -801,7 +756,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, } else if (subframe == 8) { // ACK subframes 4 candidate_dl[0] = 4; } else { - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-subframe %d for tdd_config %d\n", ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config); return(0); } @@ -815,8 +770,8 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, } } if (last_dl >= 10) { - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", - ue->Mod_id,proc->frame_tx,last_dl,frame_parms->tdd_config); + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal rx-subframe %d (tx-subframe %d) for tdd_config %d\n", + ue->Mod_id,proc->frame_tx,last_dl,subframe,frame_parms->tdd_config); return (0); } @@ -826,7 +781,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, last_dl); // i=0 - nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[last_dl]; + nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[last_dl]; n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; harq_ack0 = b[0]; @@ -868,19 +823,24 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, // This is the offset for a particular subframe (2,3,4) => (0,2,4) last_dl = (subframe-2)<<1; // i=0 - nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[5+last_dl]; + nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[5+last_dl]; n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; // i=1 - nCCE1 = ue->pdcch_vars[eNB_id]->nCCE[(6+last_dl)%10]; + nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(6+last_dl)%10]; n1_pucch1 = 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[eNB_id][0]->harq_ack[(6+last_dl)%10].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed - harq_ack1 = ue->dlsch[eNB_id][0]->harq_ack[(6+last_dl)%10].ack; + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+last_dl)%10].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed + harq_ack1 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+last_dl)%10].ack; - if (ue->dlsch[eNB_id][0]->harq_ack[5+last_dl].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed - harq_ack0 = ue->dlsch[eNB_id][0]->harq_ack[5+last_dl].ack; + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[5+last_dl].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + harq_ack0 = ue->dlsch[proc->subframe_rx&0x1][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->subframe_tx, + nCCE0,n1_pucch0, + nCCE1,n1_pucch1); if (harq_ack1!=2) { // n-6 // subframe 6,8,0 and maybe 5,7,9 is to be ACK/NAKed @@ -937,6 +897,239 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, 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 subframe 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 subframe (2,3,4) => (0,2,4) + //last_dl = (subframe-2)<<1; + if (subframe == 2) { + // i=0 + //nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[2+subframe]; + nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(8+subframe)%10]; + n1_pucch0 = 2*get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=1 + nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[2+subframe]; + n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,0) + get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; + // i=2 + nCCE2 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(8+subframe)%10]; + n1_pucch2 = 2*get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=3 + //nCCE3 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(9+subframe)%10]; + //n1_pucch3 = 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[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(8+subframe)%10].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed + harq_ack0 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(8+subframe)%10].ack; + + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[2+subframe].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + harq_ack1 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[2+subframe].ack; + + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[3+subframe].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed + harq_ack2 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[3+subframe].ack; + + //if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(9+subframe)%10].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + //harq_ack3 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(9+subframe)%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->subframe_tx, + // nCCE0,n1_pucch0, + // nCCE1,n1_pucch1, nCCE2, n1_pucch2); + }else if (subframe == 3) { + // i=0 + + nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[4+subframe]; + n1_pucch0 = 3*get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=1 + nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[5+subframe]; + n1_pucch1 = 2*get_Np(frame_parms->N_RB_DL,nCCE1,0) + get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; + // i=2 + nCCE2 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(6+subframe)]; + n1_pucch2 = get_Np(frame_parms->N_RB_DL,nCCE2,0) + 2*get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN; + // i=3 + nCCE3 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(3+subframe)]; + n1_pucch3 = 3*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[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[4+subframe].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed + harq_ack0 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[4+subframe].ack; + + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[5+subframe].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + harq_ack1 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[5+subframe].ack; + + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+subframe)].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed + harq_ack2 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+subframe)].ack; + + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(3+subframe)].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + harq_ack3 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(3+subframe)].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->subframe_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, + if ((harq_ack0!=2) ) { + b[0] = harq_ack0; + n1_pucch_inter = n1_pucch0; + } + if ((harq_ack1!=2) ) { + b[0] = b[0]&harq_ack1; + n1_pucch_inter = n1_pucch1; + } + if ((harq_ack2!=2) ) { + b[0] = b[0]&harq_ack2; + n1_pucch_inter = n1_pucch2; + } + if ((harq_ack3!=2) ) { + b[0] = b[0]&harq_ack3; + n1_pucch_inter = n1_pucch3; + } + + if (subframe == 3) { + n1_pucch_inter = n1_pucch2; + } else if (subframe == 2) { + n1_pucch_inter = n1_pucch2; + } + + //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->subframe_tx,n1_pucch_inter, + // b[0],b[1]); + + return(n1_pucch_inter); + + } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 + + if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) { + b[1] = 1; + b[0] = 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[1] = 1; + b[0] = 1; + return(n1_pucch2); + } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { + b[1] = 1; + b[0] = 0; + return(n1_pucch1); + } else if ((harq_ack0 == 0) && (harq_ack1 == 2) && (harq_ack2 == 2) && (harq_ack3 == 2)) { + b[1] = 1; + b[0] = 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[1] = 1; + b[0] = 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[1] = 1; + b[0] = 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 (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==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 } @@ -986,10 +1179,10 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt int subframe_tx = proc->subframe_tx; int frame_tx = proc->frame_tx; int ulsch_start; -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) int overflow=0; +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) int k,l; - int dummy_tx_buffer[3840*4] __attribute__((aligned(16))); + int dummy_tx_buffer[frame_parms->samples_per_tti] __attribute__((aligned(16))); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN); @@ -1015,17 +1208,22 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance; #endif //else EXMIMO -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) +//#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) if (empty_subframe) { //#if 1 overflow = ulsch_start - 9*frame_parms->samples_per_tti; for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { - memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*cmin(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti)); - - if (overflow> 0) - memset(&ue->common_vars.txdata[aa][0],0,4*overflow); + if (overflow > 0) + { + memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_tti-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_tti); + } } /*#else overflow = ulsch_start - 9*frame_parms->samples_per_tti; @@ -1043,7 +1241,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt #endif*/ return; } -#endif +//#endif if ((frame_tx%100) == 0) LOG_D(PHY,"[UE %d] Frame %d, subframe %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", @@ -1277,8 +1475,11 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32))); uint8_t access_mode; uint8_t Nbundled=0; - uint8_t ack_status=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 subframe relationship @@ -1360,7 +1561,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB } if (isBad) { - LOG_D(PHY,"Skip PUSCH generation!\n"); + LOG_I(PHY,"Skip PUSCH generation!\n"); ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; } } @@ -1378,51 +1579,77 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; } - ack_status = reset_ack(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_ack, - subframe_tx, - ue->ulsch[eNB_id]->o_ACK); - Nbundled = ack_status; + ack_status_cw0 = reset_ack(&ue->frame_parms, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack, + subframe_tx, + proc->subframe_rx, + ue->ulsch[eNB_id]->o_ACK, + &Nbundled, + 0); + ack_status_cw1 = reset_ack(&ue->frame_parms, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][1]->harq_ack, + subframe_tx, + proc->subframe_rx, + ue->ulsch[eNB_id]->o_ACK, + &NbundledCw1, + 1); + + //Nbundled = ue->dlsch[proc->subframe_rx&0x1][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 > 0) { + if (ack_status_cw0 > 0) { // check if we received a PDSCH at subframe_tx - 4 // ==> send ACK/NACK on PUSCH - ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = ack_status; + 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(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[eNB_id][0]->rnti), - T_INT(ue->dlsch[eNB_id][0]->current_harq_pid)); + T(T_UE_PHY_DLSCH_UE_ACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti), + T_INT(ue->dlsch[proc->subframe_rx&0x1][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(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[eNB_id][0]->rnti), - T_INT(ue->dlsch[eNB_id][0]->current_harq_pid)); + T(T_UE_PHY_DLSCH_UE_NACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti), + T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->current_harq_pid)); } #endif - LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n", + LOG_D(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,subframe_tx, + frame_tx%1024,subframe_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); } #ifdef DEBUG_PHY_PROC LOG_D(PHY, - "[UE %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d, bundling %d\n", - Mod_id,harq_pid,frame_tx,subframe_tx, + "[UE %d][PUSCH %d] AbsSubframe %d.%d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %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,subframe_tx, first_rb,nb_rb, ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs, @@ -1435,7 +1662,11 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe_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, - ue->ulsch[eNB_id]->bundling); + ack_status_cw0, + ack_status_cw1, + ue->ulsch[eNB_id]->bundling, Nbundled, + cqi_status, + ri_status); #endif @@ -1466,18 +1697,20 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB ue, harq_pid, eNB_id, + proc->subframe_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); stop_meas(&ue->phy_proc_tx); + //printf("------FULL TX PROC : %5.2f ------\n",ue->phy_proc_tx.p_time/(cpuf*1000.0)); return; } } #ifdef PHY_ABSTRACTION else { - ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,harq_pid,0); + ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,proc->subframe_rx,harq_pid,0); } #endif @@ -1537,6 +1770,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB ue, harq_pid, eNB_id, + proc->subframe_rx, ue->transmission_mode[eNB_id],0, Nbundled)!=0) { LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); @@ -1548,7 +1782,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB #ifdef PHY_ABSTRACTION else { - ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,proc->subframe_rx,harq_pid,0); } #endif @@ -1577,8 +1811,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB T(T_UE_PHY_PUSCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(subframe_tx),T_INT(ue->tx_power_dBm[subframe_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 - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", - Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm[subframe_tx],ue->tx_power_max_dBm, tx_amp); + LOG_D(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,subframe_tx,ue->tx_power_dBm[subframe_tx],ue->tx_power_max_dBm, tx_amp); start_meas(&ue->ulsch_modulation_stats); ulsch_modulation(ue->common_vars.txdataF, tx_amp, @@ -1656,7 +1890,13 @@ void ue_srs_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8 nb_rb_srs, tx_amp); - generate_srs_tx(ue, eNB_id, tx_amp, subframe_tx); + uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12; + uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((subframe_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, + subframe_tx); } } @@ -1665,11 +1905,16 @@ int16_t get_pucch2_cqi(PHY_VARS_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) @@ -1684,17 +1929,81 @@ int16_t get_pucch2_ri(PHY_VARS_UE *ue,int eNB_id) { return(1); } + +void get_pucch_param(PHY_VARS_UE *ue, + UE_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] = get_n1_pucch(ue, + proc, + ue->dlsch[proc->subframe_rx&0x1][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(); + } +} + void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { - uint8_t pucch_ack_payload[2]; - uint8_t n1_pucch,n2_pucch; + uint8_t pucch_ack_payload[2]; + uint8_t n2_pucch = -1; + uint16_t pucch_resource; ANFBmode_t bundling_flag; PUCCH_FMT_t format; - uint8_t SR_payload; - uint16_t CQI_payload; - uint16_t RI_payload; + uint8_t SR_payload; + uint8_t pucch_payload[2]; + uint16_t len; LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; int frame_tx=proc->frame_tx; @@ -1703,8 +2012,11 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin int CC_id = ue->CC_id; int tx_amp; int16_t Po_PUCCH; - uint8_t ack_status=0; - uint8_t ack_sr_generated = 0; + 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); @@ -1741,312 +2053,258 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin LOG_D(PHY,"[UE] PUCCH 1b\n"); } - // Check for SR and do ACK/NACK accordingly - if (is_SR_TXOp(ue,proc,eNB_id)==1) { - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d: got SR_TXOp, Checking for SR for PUSCH from MAC\n", - Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx); - - if (ue->mac_enabled==1) { - SR_payload = mac_xface->ue_get_SR(Mod_id, - CC_id, - frame_tx, - eNB_id, - ue->pdcch_vars[eNB_id]->crnti, - subframe_tx); // subframe used for meas gap - } - else { - SR_payload = 1; - } - - if (SR_payload>0) { - ue->generate_ul_signal[eNB_id] = 1; - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d got the SR for PUSCH is %d\n", - Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx,SR_payload); - } else { - ue->sr[subframe_tx]=0; - } - } else { - SR_payload=0; - } - - ack_status = get_ack(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_ack, - subframe_tx,pucch_ack_payload); - if (ack_status > 0) { - // we need to transmit ACK/NAK in this subframe - - ue->generate_ul_signal[eNB_id] = 1; - ack_sr_generated = 1; - - if ((frame_parms->frame_type == TDD) && (SR_payload>0)) { - format = pucch_format1b; - } - - n1_pucch = get_n1_pucch(ue, - proc, - ue->dlsch[eNB_id][0]->harq_ack, - eNB_id, - pucch_ack_payload, - SR_payload); - - if (ue->mac_enabled == 1) { - Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format); - } - else { - Po_PUCCH = ue->tx_power_max_dBm; - } - ue->tx_power_dBm[subframe_tx] = Po_PUCCH; - ue->tx_total_RE[subframe_tx] = 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - 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(subframe_tx),T_INT(ue->tx_power_dBm[subframe_tx]), - T_INT(tx_amp),T_INT(ue->dlsch[eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); -#endif - if (SR_payload>0) { - LOG_D(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[eNB_id][0]->rnti, - frame_tx % 1024, subframe_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, - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - Po_PUCCH, - tx_amp); - } else { - LOG_D(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[eNB_id][0]->rnti, - frame_tx, subframe_tx,ue->rx_offset_diff, - (format == pucch_format1a? "1a": ( - format == pucch_format1b? "1b" : "??")), - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, - isShortenPucch, - n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload, - Po_PUCCH, - tx_amp); - } - -#if T_TRACER - if(pucch_ack_payload[0]) - { - LOG_I(PHY,"PUCCH ACK\n"); - T(T_UE_PHY_DLSCH_UE_ACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[eNB_id][0]->rnti), - T_INT(ue->dlsch[eNB_id][0]->current_harq_pid)); - } - else - { - LOG_I(PHY,"PUCCH NACK\n"); - T(T_UE_PHY_DLSCH_UE_NACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[eNB_id][0]->rnti), - T_INT(ue->dlsch[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], - n1_pucch, - isShortenPucch, // shortened format - pucch_ack_payload, - tx_amp, - subframe_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_ack_payload, - SR_payload); -#endif - } - } else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC + // Part - I + // Collect feedback that should be transmitted at this subframe + // - SR + // - ACK/NACK + // - CQI + // - RI + + SR_payload = 0; + if (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[proc->subframe_rx & 0x1][eNB_id]->crnti, + subframe_tx); // subframe used for meas gap + } + else { + SR_payload = 1; + } + } - ack_sr_generated = 1; - if (ue->mac_enabled == 1) { - Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,pucch_format1); - } - else { - Po_PUCCH = ue->tx_power_max_dBm; - } - ue->tx_power_dBm[subframe_tx] = Po_PUCCH; - ue->tx_total_RE[subframe_tx] = 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - 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(subframe_tx),T_INT(ue->tx_power_dBm[subframe_tx]), - T_INT(tx_amp),T_INT(ue->dlsch[eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); -#endif - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %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[eNB_id][0]->rnti, - frame_tx, subframe_tx, - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, - isShortenPucch, - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - Po_PUCCH); - - if (abstraction_flag == 0) { - - generate_pucch1x(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - pucch_format1, - &ue->pucch_config_dedicated[eNB_id], - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - isShortenPucch, // shortened format - pucch_ack_payload, // this is ignored anyway, we just need a pointer - tx_amp, - subframe_tx); - } else { - LOG_D(PHY,"Calling generate_pucch_emul ...\n"); - generate_pucch_emul(ue, - proc, - pucch_format1, - ue->frame_parms.pucch_config_common.nCS_AN, - pucch_ack_payload, - SR_payload); + ack_status_cw0 = get_ack(&ue->frame_parms, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack, + subframe_tx, + proc->subframe_rx, + pucch_ack_payload, + 0); - } - } // SR_Payload==1 + ack_status_cw1 = get_ack(&ue->frame_parms, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][1]->harq_ack, + subframe_tx, + proc->subframe_rx, + pucch_ack_payload, + 1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT); - - // PUCCH 2x + nb_cw = ( (ack_status_cw0 != 0) ? 1:0) + ( (ack_status_cw1 != 0) ? 1:0); - if (ack_sr_generated == 0) { // we have not generated ACK/NAK/SR in this subframe + cqi_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&& + (is_cqi_TXOp(ue,proc,eNB_id)==1)); - n2_pucch = ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex; - // only use format2 for now, i.e. now ACK/NAK - CQI multiplexing - format = pucch_format2; + ri_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && + (is_ri_TXOp(ue,proc,eNB_id)==1)); - // Periodic CQI report - if ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&& - (is_cqi_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, subframe_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); + // 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, subframe_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 = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format); + Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format); } else { - Po_PUCCH = ue->tx_power_max_dBm; + Po_PUCCH = ue->tx_power_max_dBm; } ue->tx_power_dBm[subframe_tx] = Po_PUCCH; ue->tx_total_RE[subframe_tx] = 12; - + #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(Po_PUCCH, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 1); + 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(subframe_tx),T_INT(ue->tx_power_dBm[subframe_tx]), - T_INT(tx_amp),T_INT(ue->dlsch[eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); + T_INT(tx_amp),T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); #endif - - int len; - // get the payload : < 12 bits, returned in len - CQI_payload = get_pucch2_cqi(ue,eNB_id,&len); - generate_pucch2x(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - format, - &ue->pucch_config_dedicated[eNB_id], - n2_pucch, - &CQI_payload, - len, // A - 0, // B2 not needed - tx_amp, - subframe_tx, - ue->pdcch_vars[eNB_id]->crnti); + if(format == pucch_format1) + { + LOG_D(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[proc->subframe_rx&0x1][eNB_id][0]->rnti, + frame_tx%1024, subframe_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_D(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[proc->subframe_rx&0x1][eNB_id][0]->rnti, + frame_tx % 1024, subframe_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_D(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[proc->subframe_rx&0x1][eNB_id][0]->rnti, + frame_tx%1024, subframe_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); + } + } - ue->generate_ul_signal[eNB_id] = 1; +#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(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti), + T_INT(ue->dlsch[proc->subframe_rx&0x1][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(subframe_tx), T_INT(Mod_id), T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti), + T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->current_harq_pid)); + } +#endif - LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (CQI %d), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n", - Mod_id, - ue->dlsch[eNB_id][0]->rnti, - frame_tx, subframe_tx,CQI_payload, - n2_pucch, - Po_PUCCH, - isShortenPucch, - tx_amp); + if (abstraction_flag == 0) { - } - // Periodic RI report - else if ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && - (is_ri_TXOp(ue,proc,eNB_id)==1)){ + 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, + subframe_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 = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format); + Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format); } else { - Po_PUCCH = ue->tx_power_max_dBm; + Po_PUCCH = ue->tx_power_max_dBm; } ue->tx_power_dBm[subframe_tx] = Po_PUCCH; ue->tx_total_RE[subframe_tx] = 12; -#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(subframe_tx),T_INT(ue->tx_power_dBm[subframe_tx]), - T_INT(tx_amp),T_INT(ue->dlsch[eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); -#endif + #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 1); + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 1); #else tx_amp = AMP; #endif - LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (RI), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n", - Mod_id, - ue->dlsch[eNB_id][0]->rnti, - frame_tx, subframe_tx, - n2_pucch, - Po_PUCCH, - isShortenPucch, - tx_amp); +#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(subframe_tx),T_INT(ue->tx_power_dBm[subframe_tx]), + T_INT(tx_amp),T_INT(ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->g_pucch),T_INT(get_PL(ue->Mod_id,ue->CC_id,eNB_id))); +#endif - RI_payload = get_pucch2_ri(ue,eNB_id); + LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (RI or CQI), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n", + Mod_id, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti, + frame_tx%1024, subframe_tx, + n2_pucch, + Po_PUCCH, + isShortenPucch, + tx_amp); generate_pucch2x(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - format, - &ue->pucch_config_dedicated[eNB_id], - n2_pucch, - &RI_payload, - 1, // A - 0, // B2 not needed - tx_amp, - subframe_tx, - ue->pdcch_vars[eNB_id]->crnti); - - ue->generate_ul_signal[eNB_id] = 1; - } + &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, + subframe_tx, + ue->pdcch_vars[proc->subframe_rx & 0x1][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[proc->subframe_rx&0x1][eNB_id][0]->rnti, + frame_tx%1024, subframe_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[proc->subframe_rx&0x1][eNB_id][0]->rnti, + frame_tx%1024, subframe_tx); + break; + default: + break; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT); @@ -2061,9 +2319,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui int subframe_tx = proc->subframe_tx; int frame_tx = proc->frame_tx; unsigned int aa; - - - + uint8_t isSubframeSRS; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); @@ -2091,7 +2347,9 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui if (ue->UE_mode[eNB_id] != PRACH) { // check cell srs subframe and ue srs subframe. This has an impact on pusch encoding - ue_compute_srs_occasion(ue,proc,eNB_id); + isSubframeSRS = is_srs_occasion_common(&ue->frame_parms,proc->frame_tx,proc->subframe_tx); + + ue_compute_srs_occasion(ue,proc,eNB_id,isSubframeSRS); ue_ulsch_uespec_procedures(ue,proc,eNB_id,abstraction_flag); @@ -2139,6 +2397,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui ue, harq_pid, eNB_id, + proc->subframe_rx, ue->transmission_mode[eNB_id],0, 0)!=0) { // Nbundled, to be updated!!!! LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); @@ -2148,7 +2407,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui #ifdef PHY_ABSTRACTION else { - ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,proc->subframe_rx,harq_pid,0); } #endif @@ -2183,17 +2442,34 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui } // reset DL ACK/NACK status - reset_ack(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_ack, - subframe_tx, - ue->ulsch[eNB_id]->o_ACK); + uint8_t N_bundled = 0; + if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0] != NULL) + { + reset_ack(&ue->frame_parms, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack, + subframe_tx, + proc->subframe_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + reset_ack(&ue->frame_parms, + ue->dlsch[(proc->subframe_rx+1)&0x1][eNB_id][0]->harq_ack, + subframe_tx, + proc->subframe_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + } - if (ue->dlsch_SI[eNB_id]) + if (ue->dlsch_SI[eNB_id] != NULL) reset_ack(&ue->frame_parms, - ue->dlsch_SI[eNB_id]->harq_ack, - subframe_tx, - ue->ulsch[eNB_id]->o_ACK); - + ue->dlsch_SI[eNB_id]->harq_ack, + subframe_tx, + proc->subframe_rx, + ue->ulsch[eNB_id]->o_ACK, + &N_bundled, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); stop_meas(&ue->phy_proc_tx); @@ -2228,6 +2504,8 @@ void ue_measurement_procedures( 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); + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; @@ -2267,6 +2545,7 @@ void ue_measurement_procedures( 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, @@ -2382,8 +2661,8 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t 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[eNB_id][0]->pmi_alloc; - emos_dump_UE.mcs = ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs; + emos_dump_UE.pmi_saved = ue->dlsch[subframe&0x1][eNB_id][0]->pmi_alloc; + emos_dump_UE.mcs = ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[ue->dlsch[subframe&0x1][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)); @@ -2425,10 +2704,15 @@ void restart_phy(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t ab ue->pbch_vars[eNB_id]->pdu_errors_conseq=0; ue->pbch_vars[eNB_id]->pdu_errors=0; - ue->pdcch_vars[eNB_id]->dci_errors = 0; - ue->pdcch_vars[eNB_id]->dci_missed = 0; - ue->pdcch_vars[eNB_id]->dci_false = 0; - ue->pdcch_vars[eNB_id]->dci_received = 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; @@ -2606,19 +2890,19 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uin #endif } else { - + /* LOG_E(PHY,"[UE %d] frame %d, subframe %d, Error decoding PBCH!\n", ue->Mod_id,frame_rx, subframe_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_tti,1,1); - write_output("H00.m","h00",&(ue->common_vars.common_vars_rx_data_per_thread[0].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.common_vars_rx_data_per_thread[0].dl_ch_estimates[0][2][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),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.common_vars_rx_data_per_thread[0].rxdataF[0],8*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); @@ -2676,9 +2960,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint if (abstraction_flag == 0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); - rx_pdcch(&ue->common_vars, - ue->pdcch_vars, - &ue->frame_parms, + rx_pdcch(ue, proc->frame_rx, subframe_rx, eNB_id, @@ -2724,14 +3006,14 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint } LOG_D(PHY,"Calling dci_decoding_proc_emul ...\n"); - dci_cnt = dci_decoding_procedure_emul(ue->pdcch_vars, + dci_cnt = dci_decoding_procedure_emul(ue->pdcch_vars[subframe_rx&1], PHY_vars_eNB_g[i][CC_id]->num_ue_spec_dci[subframe_rx&1], PHY_vars_eNB_g[i][CC_id]->num_common_dci[subframe_rx&1], PHY_vars_eNB_g[i][CC_id]->dci_alloc[subframe_rx&1], dci_alloc_rx, eNB_id); // printf("DCI: dci_cnt %d\n",dci_cnt); - UE_id = (uint32_t)find_ue((int16_t)ue->pdcch_vars[eNB_id]->crnti,PHY_vars_eNB_g[i][CC_id]); + UE_id = (uint32_t)find_ue((int16_t)ue->pdcch_vars[subframe_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); @@ -2754,9 +3036,14 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint #endif - LOG_D(PHY,"[UE %d] AbsSubFrame %d.%d, Mode %s: DCI found %i\n",ue->Mod_id,frame_rx%1024,subframe_rx,mode_string[ue->UE_mode[eNB_id]],dci_cnt); + 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,subframe_rx,mode_string[ue->UE_mode[eNB_id]], + dci_cnt, + dci_alloc_rx[0].rnti, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, + dci_alloc_rx[0].format ); - ue->pdcch_vars[eNB_id]->dci_received += dci_cnt; + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->dci_received += dci_cnt; #ifdef EMOS //emos_dump_UE.dci_cnt[subframe_rx] = dci_cnt; @@ -2767,16 +3054,16 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint if ((ue->UE_mode[eNB_id]>PRACH) && - (dci_alloc_rx[i].rnti == ue->pdcch_vars[eNB_id]->crnti) && + (dci_alloc_rx[i].rnti == ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti) && (dci_alloc_rx[i].format != format0)) { - LOG_D(PHY,"[UE %d][DCI][PDSCH %x] frame %d, subframe %d: format %d, num_pdcch_symbols %d, nCCE %d, total CCEs %d\n", + 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,subframe_rx, + frame_rx%1024,subframe_rx, dci_alloc_rx[i].format, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - ue->pdcch_vars[eNB_id]->nCCE[subframe_rx], + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->nCCE[subframe_rx], get_nCCE(3,&ue->frame_parms,get_mi(&ue->frame_parms,0))); @@ -2788,24 +3075,26 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint (generate_ue_dlsch_params_from_dci(frame_rx, subframe_rx, (void *)&dci_alloc_rx[i].dci_pdu, - ue->pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, dci_alloc_rx[i].format, - ue->dlsch[eNB_id], + ue->dlsch[subframe_rx&0x1][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[eNB_id]->crnti_is_temporary? ue->pdcch_vars[eNB_id]->crnti: 0)==0)) { + ue->pdcch_vars[0&0x1][eNB_id]->crnti_is_temporary? ue->pdcch_vars[subframe_rx & 0x1][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 == format2A) || + (dci_alloc_rx[i].format == format2B)) { - ue->dlsch[eNB_id][0]->g_pucch += ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->delta_PUCCH; + ue->dlsch[subframe_rx&0x1][eNB_id][0]->g_pucch += ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_processes[ue->dlsch[subframe_rx&0x1][eNB_id][0]->current_harq_pid]->delta_PUCCH; } ue->dlsch_received[eNB_id]++; @@ -2813,13 +3102,13 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint #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 subframe %d=> %d\n",ue->Mod_id,subframe_rx,ue->dlsch[eNB_id][0]->active); + LOG_D(PHY,"[UE %d] *********** dlsch->active in subframe %d=> %d\n",ue->Mod_id,subframe_rx,ue->dlsch[subframe_rx&0x1][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_D(PHY,"[UE %d] Frame %d, subframe %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,subframe_rx,ue->pdcch_vars[eNB_id]->crnti); + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,subframe_rx,ue->pdcch_vars[subframe_rx&1][eNB_id]->crnti); #endif //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); ue->UE_mode[eNB_id] = PUSCH; @@ -2927,7 +3216,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint 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[eNB_id]->crnti) && + } else if( (dci_alloc_rx[i].rnti == ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti) && (dci_alloc_rx[i].format == format0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d: Found rnti %x, format 0, dci_cnt %d\n", @@ -2939,7 +3228,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint if ((ue->UE_mode[eNB_id] > PRACH) && (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, - ue->pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, subframe_rx, format0, ue, @@ -2970,14 +3259,17 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint #endif } - } - /* else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) && + } 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 subframe %d: Found cba rnti %x, format 0, dci_cnt %d\n", ue->Mod_id,frame_rx,subframe_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; @@ -3001,12 +3293,13 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); #endif ue->ulsch[eNB_id]->num_cba_dci[(subframe_rx+4)%10]++; - } - */ + } + } + else { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] frame %d, subframe %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",ue->Mod_id,frame_rx,subframe_rx,i,dci_alloc_rx[i].rnti, - ue->pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, ue->ulsch[eNB_id]->cba_rnti[0], dci_alloc_rx[i].format); // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); @@ -3026,7 +3319,9 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs int subframe_rx = proc->subframe_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; @@ -3037,7 +3332,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation\n", ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) pmch_mcs = mac_xface->ue_query_mch(ue->Mod_id, CC_id, frame_rx, @@ -3135,7 +3430,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs if (subframe_rx==9) mac_xface->macphy_exit("Why are we exiting here?"); } else { // decoding successful -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (mcch_active == 1) { mac_xface->ue_send_mch_sdu(ue->Mod_id, @@ -3157,12 +3452,54 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs } -#endif // Rel10 +#endif // Rel10 || Rel14 } // decoding sucessful } // pmch_mcs>=0 } // is_pmch_subframe=true } +void copy_harq_proc_struct(LTE_DL_UE_HARQ_t *harq_processes_dest, LTE_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(harq_status_t *harq_ack_dest, harq_status_t *current_harq_ack) +{ + memcpy(harq_ack_dest, current_harq_ack, sizeof(harq_status_t)); +} + void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSCH_t pdsch, LTE_UE_DLSCH_t *dlsch0, LTE_UE_DLSCH_t *dlsch1, int s0, int s1, int abstraction_flag) { int subframe_rx = proc->subframe_rx; @@ -3178,7 +3515,7 @@ void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSC if (dlsch0 && (!dlsch1)) { harq_pid = dlsch0->current_harq_pid; - LOG_D(PHY,"[UE %d] PDSCH active in subframe %d, harq_pid %d\n",ue->Mod_id,subframe_rx,harq_pid); + LOG_D(PHY,"[UE %d] PDSCH active in subframe %d, harq_pid %d Symbol %d\n",ue->Mod_id,subframe_rx,harq_pid,m); if ((pdsch==PDSCH) && (ue->transmission_mode[eNB_id] == 5) && @@ -3187,7 +3524,14 @@ void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSC dual_stream_UE = 1; eNB_id_i = ue->n_connected_eNB; i_mod = dlsch0->harq_processes[harq_pid]->Qm; - } else { + } + 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; @@ -3255,21 +3599,24 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo frame_rx, ue->prach_resources[eNB_id]->ra_RNTI, dlsch0->harq_processes[0]->b, - &ue->pdcch_vars[eNB_id]->crnti, - ue->prach_resources[eNB_id]->ra_PreambleIndex); + &ue->pdcch_vars[subframe_rx & 0x1][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[(subframe_rx+1) & 0x1][eNB_id]->crnti = ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti; if (timing_advance!=0xffff) { - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Got rnti %x and timing advance %d from RAR\n", - ue->Mod_id, - frame_rx, - subframe_rx, - ue->pdcch_vars[eNB_id]->crnti, - timing_advance); + LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Got rnti %x and timing advance %d from RAR\n", + ue->Mod_id, + frame_rx, + subframe_rx, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, + timing_advance); // remember this c-rnti is still a tc-rnti - ue->pdcch_vars[eNB_id]->crnti_is_temporary = 1; + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti_is_temporary = 1; //timing_advance = 0; process_timing_advance_rar(ue,proc,timing_advance); @@ -3326,11 +3673,34 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, int harq_pid; int frame_rx = proc->frame_rx; int subframe_rx = proc->subframe_rx; - int ret=0; + int ret=0, ret1=0; int CC_id = ue->CC_id; LTE_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, subframe_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, subframe_rx, harq_pid, is_cw1_active); - if (dlsch0 && (!dlsch1)) { + 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]; @@ -3356,8 +3726,6 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, break; } - - harq_pid = dlsch0->current_harq_pid; if (frame_rx < *dlsch_errors) *dlsch_errors=0; @@ -3374,12 +3742,13 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, 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[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, frame_rx, subframe_rx, ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); @@ -3392,8 +3761,19 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, 0, subframe_rx<<1); stop_meas(&ue->dlsch_unscrambling_stats); - - start_meas(&ue->dlsch_decoding_stats); + +#if 0 + LOG_I(PHY," ------ start turbo decoder for AbsSubframe %d.%d / %d ------ \n", frame_rx, subframe_rx, harq_pid); + LOG_I(PHY,"start turbo decode for CW 0 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, subframe_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, subframe_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, subframe_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, subframe_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, subframe_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, subframe_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, subframe_rx, harq_pid, ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols); +#endif + + start_meas(&ue->dlsch_decoding_stats[subframe_rx&0x1]); ret = dlsch_decoding(ue, pdsch_vars->llr[0], &ue->frame_parms, @@ -3404,7 +3784,69 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, harq_pid, pdsch==PDSCH?1:0, dlsch0->harq_processes[harq_pid]->TBS>256?1:0); - stop_meas(&ue->dlsch_decoding_stats); + stop_meas(&ue->dlsch_decoding_stats[subframe_rx&0x1]); + + LOG_D(PHY," --> Unscrambling for CW0 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_D(PHY,"AbsSubframe %d.%d --> Turbo Decoding for CW0 %5.3f\n", + frame_rx%1024, subframe_rx,(ue->dlsch_decoding_stats[subframe_rx&0x1].p_time)/(cpuf*1000.0)); + + + 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[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, + frame_rx, + subframe_rx, + ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); + + start_meas(&ue->dlsch_unscrambling_stats); + dlsch_unscrambling(&ue->frame_parms, + 0, + dlsch1, + dlsch1->harq_processes[harq_pid]->G, + pdsch_vars->llr[1], + 1, + subframe_rx<<1); + stop_meas(&ue->dlsch_unscrambling_stats); + +#if 0 + LOG_I(PHY,"start turbo decode for CW 1 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, subframe_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, subframe_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, subframe_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, subframe_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, subframe_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, subframe_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, subframe_rx, harq_pid, ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols); +#endif + + start_meas(&ue->dlsch_decoding_stats[subframe_rx&0x1]); + + ret1 = dlsch_decoding(ue, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + subframe_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + stop_meas(&ue->dlsch_decoding_stats[subframe_rx&0x1]); + + + 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, subframe_rx,(ue->dlsch_decoding_stats[subframe_rx&0x1].p_time)/(cpuf*1000.0)); + } + + LOG_D(PHY," ------ end turbo decoder for AbsSubframe %d.%d ------ \n", frame_rx, subframe_rx); } else { @@ -3417,15 +3859,17 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, #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] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", + 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,subframe_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); } @@ -3434,10 +3878,11 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, } else { if(dlsch0->rnti != 0xffff) { - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: Received DLSCH (rv %d,mcs %d,TBS %d)\n", + 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,subframe_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); } @@ -3499,6 +3944,49 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, 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 subframe %d DLSCH CW1 in error (rv %d,mcs %d,TBS %d)\n", + ue->Mod_id,dlsch0->rnti, + harq_pid,frame_rx,subframe_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 subframe %d: Received DLSCH CW1 (rv %d,mcs %d,TBS %d)\n", + ue->Mod_id,dlsch0->rnti, + harq_pid,frame_rx,subframe_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, + subframe_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 @@ -3547,16 +4035,20 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin T_BUFFER(&ue->common_vars.rxdata[0][subframe_rx*ue->frame_parms.samples_per_tti], ue->frame_parms.samples_per_tti * 4)); - start_meas(&ue->phy_proc_rx); + // start timers + + LOG_D(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, subframe_rx); + start_meas(&ue->phy_proc_rx[subframe_rx&0x1]); + start_meas(&ue->generic_stat); pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0; // deactivate reception until we scan pdcch - if (ue->dlsch[eNB_id][0]) - ue->dlsch[eNB_id][0]->active = 0; - if (ue->dlsch[eNB_id][1]) - ue->dlsch[eNB_id][1]->active = 0; + if (ue->dlsch[subframe_rx&0x1][eNB_id][0]) + ue->dlsch[subframe_rx&0x1][eNB_id][0]->active = 0; + if (ue->dlsch[subframe_rx&0x1][eNB_id][1]) + ue->dlsch[subframe_rx&0x1][eNB_id][1]->active = 0; if (ue->dlsch_SI[eNB_id]) ue->dlsch_SI[eNB_id]->active = 0; @@ -3599,6 +4091,9 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ l=1; } + + LOG_D(PHY," ------ slot 0 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); for (; l<=l2; l++) { if (abstraction_flag == 0) { start_meas(&ue->ofdm_demod_stats); @@ -3622,12 +4117,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,subframe_rx); return(-1); } - LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[eNB_id]->num_pdcch_symbols); + LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols); } } // for l=1..l2 ue_measurement_procedures(l-1,ue,proc,eNB_id,(subframe_rx<<1),abstraction_flag,mode); + LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); // If this is PMCH, call procedures and return if (pmch_flag == 1) { ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag); @@ -3642,21 +4138,27 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin 0); // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH) - + stop_meas(&ue->generic_stat); + LOG_D(PHY,"[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + + start_meas(&ue->generic_stat); // do procedures for C-RNTI - if (ue->dlsch[eNB_id][0]->active == 1) { + if (ue->dlsch[subframe_rx&0x1][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[eNB_id][0], + ue->dlsch[subframe_rx&0x1][eNB_id][0], NULL, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[subframe_rx & 0x1][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, subframe_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); @@ -3666,7 +4168,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin SI_PDSCH, ue->dlsch_SI[eNB_id], NULL, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[subframe_rx & 0x1][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); @@ -3681,7 +4183,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin P_PDSCH, ue->dlsch_p[eNB_id], NULL, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[subframe_rx & 0x1][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); @@ -3696,12 +4198,15 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin RA_PDSCH, ue->dlsch_ra[eNB_id], NULL, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[subframe_rx & 0x1][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, subframe_rx); + LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + if (subframe_select(&ue->frame_parms,subframe_rx) != SF_S) { // do front-end processing for second slot, and first symbol of next subframe for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) { if (abstraction_flag == 0) { @@ -3734,35 +4239,75 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin } } // not an S-subframe - // run pbch procedures if subframe is 0 - if (subframe_rx == 0) + stop_meas(&ue->generic_stat); + + LOG_D(PHY,"[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); + LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + + if ( (subframe_rx == 0) && (ue->decode_MIB == 1)) + { ue_pbch_procedures(eNB_id,ue,proc,abstraction_flag); + } // do procedures for C-RNTI - if (ue->dlsch[eNB_id][0]->active == 1) { + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + if (ue->dlsch[subframe_rx&0x1][eNB_id][0]->active == 1) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + start_meas(&ue->pdsch_procedures_stat); ue_pdsch_procedures(ue, proc, eNB_id, PDSCH, - ue->dlsch[eNB_id][0], + ue->dlsch[subframe_rx&0x1][eNB_id][0], NULL, 1+(ue->frame_parms.symbols_per_tti>>1), ue->frame_parms.symbols_per_tti-1, abstraction_flag); + stop_meas(&ue->pdsch_procedures_stat); + + LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); + + start_meas(&ue->dlsch_procedures_stat); ue_dlsch_procedures(ue, proc, eNB_id, PDSCH, - ue->dlsch[eNB_id][0], - NULL, + ue->dlsch[subframe_rx&0x1][eNB_id][0], + ue->dlsch[subframe_rx&0x1][eNB_id][1], &ue->dlsch_errors[eNB_id], mode, abstraction_flag); + stop_meas(&ue->dlsch_procedures_stat); + LOG_D(PHY,"[SFN %d] Slot1: Pdsch Proc %5.2f\n",subframe_rx,ue->pdsch_procedures_stat.p_time/(cpuf*1000.0)); + LOG_D(PHY,"[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",subframe_rx,ue->dlsch_procedures_stat.p_time/(cpuf*1000.0)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); } + start_meas(&ue->generic_stat); + +#if 0 + if(subframe_rx==5 && ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_processes[ue->dlsch[subframe_rx&0x1][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[subframe_rx&0x1].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[(subframe_rx+1)&0x1].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[(subframe+1)&0x1].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[subframe_rx&0x1].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[subframe_rx&0x1][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[subframe_rx&0x1][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[subframe&0x1][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[subframe&0x1][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, @@ -3833,6 +4378,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->dlsch_ra[eNB_id]->active = 0; } + // duplicate harq structure + + uint8_t current_harq_pid = ue->dlsch[subframe_rx&0x1][eNB_id][0]->current_harq_pid; + LTE_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_processes[current_harq_pid]; + LTE_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[(subframe_rx+1)&0x1][eNB_id][0]->harq_processes[current_harq_pid]; + + harq_status_t *current_harq_ack = &ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_ack[subframe_rx]; + harq_status_t *harq_ack_dest = &ue->dlsch[(subframe_rx+1)&0x1][eNB_id][0]->harq_ack[subframe_rx]; + + copy_harq_proc_struct(harq_processes_dest, current_harq_processes); + copy_ack_struct(harq_ack_dest, current_harq_ack); + if (subframe_rx==9) { if (frame_rx % 10 == 0) { if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) @@ -3857,7 +4414,8 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin } - + stop_meas(&ue->generic_stat); + //printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0)); #ifdef EMOS phy_procedures_emos_UE_RX(ue,slot,eNB_id); @@ -3865,11 +4423,14 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_rx); + stop_meas(&ue->phy_proc_rx[subframe_rx&0x1]); + + LOG_D(PHY,"------FULL RX PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->phy_proc_rx[subframe_rx&0x1].p_time/(cpuf*1000.0)); + LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, subframe_rx); return (0); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) int phy_procedures_RN_UE_RX(uint8_t slot_rx, uint8_t next_slot, relaying_type_t r_type) { @@ -3965,7 +4526,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_DL) || (ue->frame_parms.frame_type == FDD)) { -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (phy_procedures_RN_UE_RX(subframe_rx, subframe_tx, r_type) != 0 ) #endif @@ -3979,7 +4540,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_S) && (slot==0)) { -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (phy_procedures_RN_UE_RX(subframe_rx, subframe_tx, r_type) != 0 ) #endif diff --git a/openair1/SCHED/pucch_pc.c b/openair1/SCHED/pucch_pc.c index e19d3ad8c4cf3863421f9eae0b36c05be8b55bde..92e756fa7376ece8f4cdd0d79bf81e226cbcac74 100644 --- a/openair1/SCHED/pucch_pc.c +++ b/openair1/SCHED/pucch_pc.c @@ -31,6 +31,7 @@ */ #include "PHY/defs.h" +#include "SCHED/defs.h" #include "PHY/LTE_TRANSPORT/proto.h" #include "PHY/extern.h" @@ -51,7 +52,7 @@ int16_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,u Po_PUCCH = get_PL(ue->Mod_id,ue->CC_id,eNB_id)+ ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+ - ue->dlsch[eNB_id][0]->g_pucch; + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->g_pucch; switch (pucch_fmt) { case pucch_format1: @@ -85,24 +86,28 @@ int16_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,u } break; + + case pucch_format3: + fprintf(stderr, "PUCCH format 3 not handled\n"); + abort(); } if (pucch_fmt!=pucch_format1) { - LOG_D(PHY,"[UE %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n", + LOG_D(PHY,"[UE %d][PDSCH %x] AbsSubframe %d.%d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n", ue->Mod_id, - ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti,proc->frame_tx%1024,subframe, Po_PUCCH, ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, get_PL(ue->Mod_id,ue->CC_id,eNB_id), - ue->dlsch[eNB_id][0]->g_pucch); + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->g_pucch); } else { - LOG_D(PHY,"[UE %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n", + LOG_D(PHY,"[UE %d][SR %x] AbsSubframe %d.%d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n", ue->Mod_id, - ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe, + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->rnti,proc->frame_tx%1024,subframe, Po_PUCCH, ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, get_PL(ue->Mod_id,ue->CC_id,eNB_id), - ue->dlsch[eNB_id][0]->g_pucch); + ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->g_pucch); } return(Po_PUCCH); diff --git a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c index 6d3d4cabb35aacee0ce5e3e71bce097751430581..76b72e321f304901ac38c0d0e2cf72fbd3a8c460 100644 --- a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c +++ b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c @@ -488,7 +488,8 @@ void fill_phy_ue_vars(unsigned int ue_id, uint8_t CC_id,unsigned int last_slot) rnti = UE_transport_info[ue_id][CC_id].rnti[n_enb]; enb_id = UE_transport_info[ue_id][CC_id].eNB_id[n_enb]; - PHY_vars_UE_g[ue_id][CC_id]->pdcch_vars[enb_id]->crnti=rnti; + PHY_vars_UE_g[ue_id][CC_id]->pdcch_vars[0][enb_id]->crnti=rnti; + PHY_vars_UE_g[ue_id][CC_id]->pdcch_vars[1][enb_id]->crnti=rnti; harq_pid = UE_transport_info[ue_id][CC_id].harq_pid[n_enb]; diff --git a/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c b/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c index 306ec12ad28c50b8f9a0ae9609d3203cb9125083..d161da6a74d13ce32e7518f84e428d1ed69a751e 100644 --- a/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c +++ b/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c @@ -308,10 +308,10 @@ void* multicast_link_main_loop (void *param) } void multicast_link_start(void (*rx_handlerP) (unsigned int, char *), - unsigned char multicast_group, char *multicast_ifname) + unsigned char _multicast_group, char *multicast_ifname) { rx_handler = rx_handlerP; - multicast_group = multicast_group; + multicast_group = _multicast_group; multicast_if = multicast_ifname; LOG_I(EMU, "[MULTICAST] LINK START on interface=%s for group=%d: handler=%p\n", (multicast_if == NULL) ? "not specified" : multicast_if, multicast_group, diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 62b4063d298eacfe89f66e70831181dbab1d2d53..951b5f75f65c9450ee6b32f54308dff21a0c8af7 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -57,6 +57,8 @@ PHY_VARS_eNB *eNB; PHY_VARS_UE *UE; +double cpuf; + int otg_enabled=0; /*the following parameters are used to control the processing times calculations*/ double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */ @@ -118,10 +120,10 @@ void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_ } - + } -void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,double SNR, int tx_lev,int hold_channel,int abstx, int num_rounds, int trials, int round, channel_desc_t *eNB2UE[4], +void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,double SNR, int tx_lev,int hold_channel,int abstx, int num_rounds, int trials, int round, channel_desc_t *eNB2UE[4], double *s_re[2],double *s_im[2],double *r_re[2],double *r_im[2],FILE *csv_fd) { int i,u; @@ -145,17 +147,17 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou r_re[aarx][i] += ((double)(((short *)eNB->common_vars.txdata[0][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); r_im[aarx][i] += ((double)(((short *)eNB->common_vars.txdata[0][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); } - + } } } } - + // Multipath channel if (awgn_flag == 0) { multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im, 2*UE->frame_parms.samples_per_tti,hold_channel); - + // printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset); if(abstx==1 && num_rounds>1) if(round==0 && hold_channel==0) { @@ -163,7 +165,7 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou random_channel(eNB2UE[2],0); random_channel(eNB2UE[3],0); } - + if (UE->perfect_ce==1) { // fill in perfect channel estimates freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); @@ -173,15 +175,15 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou */ } } - - + + if(abstx) { if (trials==0 && round==0) { // calculate freq domain representation to compute SINR freq_channel(eNB2UE[0], eNB->frame_parms.N_RB_DL,2*eNB->frame_parms.N_RB_DL + 1); // snr=pow(10.0,.1*SNR); fprintf(csv_fd,"%f,",SNR); - + for (u=0; u<2*eNB->frame_parms.N_RB_DL; u++) { for (aarx=0; aarx<eNB2UE[0]->nb_rx; aarx++) { for (aatx=0; aatx<eNB2UE[0]->nb_tx; aatx++) { @@ -190,11 +192,11 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } - } - + } + if(num_rounds>1) { freq_channel(eNB2UE[1], eNB->frame_parms.N_RB_DL,2*eNB->frame_parms.N_RB_DL + 1); - + for (u=0; u<2*eNB->frame_parms.N_RB_DL; u++) { for (aarx=0; aarx<eNB2UE[1]->nb_rx; aarx++) { for (aatx=0; aatx<eNB2UE[1]->nb_tx; aatx++) { @@ -204,9 +206,9 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou } } } - + freq_channel(eNB2UE[2], eNB->frame_parms.N_RB_DL,2*eNB->frame_parms.N_RB_DL + 1); - + for (u=0; u<2*eNB->frame_parms.N_RB_DL; u++) { for (aarx=0; aarx<eNB2UE[2]->nb_rx; aarx++) { for (aatx=0; aatx<eNB2UE[2]->nb_tx; aatx++) { @@ -216,9 +218,9 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou } } } - + freq_channel(eNB2UE[3], eNB->frame_parms.N_RB_DL,2*eNB->frame_parms.N_RB_DL + 1); - + for (u=0; u<2*eNB->frame_parms.N_RB_DL; u++) { for (aarx=0; aarx<eNB2UE[3]->nb_rx; aarx++) { for (aatx=0; aatx<eNB2UE[3]->nb_tx; aatx++) { @@ -231,10 +233,11 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou } } } - + //AWGN - // This is the SNR on the PDSCH for OFDM symbols without pilots -> rho_A - sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(eNB->frame_parms.N_RB_DL*12)) - SNR - get_pa_dB(eNB->pdsch_config_dedicated); + // tx_lev is the average energy over the whole subframe + // but SNR should be better defined wrt the energy in the reference symbols + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(eNB->frame_parms.N_RB_DL*12)) - SNR; sigma2 = pow(10,sigma2_dB/10); for (i=0; i<2*UE->frame_parms.samples_per_tti; i++) { @@ -251,7 +254,7 @@ void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,dou void fill_DCI(PHY_VARS_eNB *eNB, DCI_ALLOC_t *dci_alloc, - int subframe, + int subframe, int n_rnti, int n_users, int transmission_mode, @@ -267,7 +270,7 @@ void fill_DCI(PHY_VARS_eNB *eNB, int *num_dci) { int k; - int dci_length,dci_length_bytes; + int dci_length = -1,dci_length_bytes = -1; // printf("Generating DCIs for %d users, TM %d, mcs1 %d\n",n_users,transmission_mode,mcs1); for(k=0; k<n_users; k++) { @@ -278,9 +281,9 @@ void fill_DCI(PHY_VARS_eNB *eNB, case 7: if (common_flag == 0) { - + if (eNB->frame_parms.frame_type == TDD) { - + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1_1_5MHz_TDD_t; @@ -294,7 +297,7 @@ void fill_DCI(PHY_VARS_eNB *eNB, ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = ndi; ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = rv; break; - + case 25: dci_length = sizeof_DCI1_5MHz_TDD_t; dci_length_bytes = sizeof(DCI1_5MHz_TDD_t); @@ -307,7 +310,7 @@ void fill_DCI(PHY_VARS_eNB *eNB, ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = ndi; ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = rv; break; - + case 50: dci_length = sizeof_DCI1_10MHz_TDD_t; dci_length_bytes = sizeof(DCI1_10MHz_TDD_t); @@ -1223,17 +1226,18 @@ DCI_PDU *get_dci_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t if (subframeP == subframe) { DCI_pdu.Num_ue_spec_dci = num_ue_spec_dci; DCI_pdu.Num_common_dci = num_common_dci; - DCI_pdu.num_pdcch_symbols = num_pdcch_symbols; - return(&DCI_pdu); + DCI_pdu.num_pdcch_symbols = num_pdcch_symbols; } else { DCI_pdu.Num_ue_spec_dci = 0; DCI_pdu.Num_common_dci = 0; - DCI_pdu.num_pdcch_symbols = num_pdcch_symbols; + DCI_pdu.num_pdcch_symbols = num_pdcch_symbols; } + + return &DCI_pdu; } void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP) { - + return; } @@ -1265,7 +1269,7 @@ int main(int argc, char **argv) int s,Kr,Kr_bytes; - double SNR,snr0=-2.0,snr1,rate; + double SNR,snr0=-2.0,snr1,rate = 0; double snr_step=1,input_snr_step=1, snr_int=30; LTE_DL_FRAME_PARMS *frame_parms; @@ -1295,10 +1299,10 @@ int main(int argc, char **argv) DCI_ALLOC_t *dci_alloc = &DCI_pdu.dci_alloc[0]; unsigned int ret; - unsigned int coded_bits_per_codeword=0,nsymb,tbs=0; + unsigned int coded_bits_per_codeword=0,nsymb; //,tbs=0; - unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0;//,num_layers; - int re_allocated; + unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors[4]={0,0,0,0};//,num_layers; + //int re_allocated; char fname[32],vname[32]; FILE *bler_fd; char bler_fname[256]; @@ -1325,25 +1329,25 @@ int main(int argc, char **argv) int n_frames; int n_ch_rlz = 1; channel_desc_t *eNB2UE[4]; - uint8_t num_pdcch_symbols_2=0; + //uint8_t num_pdcch_symbols_2=0; uint8_t rx_sample_offset = 0; //char stats_buffer[4096]; //int len; uint8_t num_rounds = 4;//,fix_rounds=0; - int u; + //int u; int n=0; int abstx=0; - int iii; + //int iii; int ch_realization; - int pmi_feedback=0; + //int pmi_feedback=0; int hold_channel=0; // void *data; // int ii; // int bler; - double blerr[4],uncoded_ber,avg_ber; + double blerr[4],uncoded_ber; //,avg_ber; short *uncoded_ber_bit=NULL; uint8_t N_RB_DL=25,osf=1; frame_t frame_type = FDD; @@ -1352,7 +1356,7 @@ int main(int argc, char **argv) char title[255]; int numCCE=0; - int dci_length_bytes=0,dci_length=0; + //int dci_length_bytes=0,dci_length=0; //double channel_bandwidth = 5.0, sampling_rate=7.68; int common_flag=0,TPC=0; @@ -1375,6 +1379,7 @@ int main(int argc, char **argv) uint8_t Kmimo; uint8_t ue_category=4; uint32_t Nsoft; + int sf; @@ -1386,9 +1391,9 @@ int main(int argc, char **argv) FILE *csv_fd=NULL; char csv_fname[32]; - int dci_flag=1; + //int dci_flag=1; int two_thread_flag=0; - int DLSCH_RB_ALLOC; + int DLSCH_RB_ALLOC = 0; #if defined(__arm__) FILE *proc_fd = NULL; @@ -1408,6 +1413,8 @@ int main(int argc, char **argv) #endif printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz); + cpuf = cpu_freq_GHz; + //signal(SIGSEGV, handler); //signal(SIGABRT, handler); @@ -1446,9 +1453,9 @@ int main(int argc, char **argv) Nid_cell = atoi(optarg); break; - case 'd': - dci_flag = 1; - break; + //case 'd': + // dci_flag = 1; + // break; case 'D': frame_type=TDD; @@ -1459,7 +1466,7 @@ int main(int argc, char **argv) common_flag = 1; TPC = atoi(optarg); break; - + case 'E': threequarter_fs=1; break; @@ -1475,7 +1482,7 @@ int main(int argc, char **argv) case 'i': input_fd = fopen(optarg,"r"); input_file=1; - dci_flag = 1; + //dci_flag = 1; break; case 'I': @@ -1779,7 +1786,7 @@ int main(int argc, char **argv) form_ue = create_lte_phy_scope_ue(); sprintf (title, "LTE PHY SCOPE eNB"); fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - + if (!dual_stream_UE==0) { UE->use_ia_receiver = 1; fl_set_button(form_ue->button_0,1); @@ -1807,9 +1814,9 @@ int main(int argc, char **argv) perfect_ce); if ((transmission_mode==1) || (transmission_mode==7)) { - for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) - for (re=0; re<eNB->frame_parms.ofdm_symbol_size; re++) - eNB->common_vars.beam_weights[0][0][aa][re] = 0x00007fff/eNB->frame_parms.nb_antennas_tx; + for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) + for (re=0; re<eNB->frame_parms.ofdm_symbol_size; re++) + eNB->common_vars.beam_weights[0][0][aa][re] = 0x00007fff/eNB->frame_parms.nb_antennas_tx; } if (transmission_mode<7) @@ -1823,15 +1830,17 @@ int main(int argc, char **argv) } else { eNB->te = dlsch_encoding_2threads; + extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *); + extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *); init_td_thread(eNB,NULL); init_te_thread(eNB,NULL); } - // callback functions required for phy_procedures_tx + // callback functions required for phy_procedures_tx mac_xface->get_dci_sdu = get_dci_sdu; mac_xface->get_dlsch_sdu = get_dlsch_sdu; mac_xface->eNB_dlsch_ulsch_scheduler = eNB_dlsch_ulsch_scheduler; - + // eNB_id_i = UE->n_connected_eNB; printf("Setting mcs1 = %d\n",mcs1); @@ -1990,7 +1999,7 @@ int main(int argc, char **argv) } */ - UE->pdcch_vars[0]->crnti = n_rnti; + UE->pdcch_vars[subframe & 0x1][0]->crnti = n_rnti; // Fill in UL_alloc UL_alloc_pdu.type = 0; @@ -2096,17 +2105,28 @@ int main(int argc, char **argv) } } - for (i=0; i<2; i++) { - UE->dlsch[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + /* allocate memory for both subframes (only one is really used + * but there is now "copy_harq_proc_struct" which needs both + * to be valid) + * TODO: refine this somehow (necessary?) + */ + for (sf = 0; sf < 2; sf++) { + for (i=0; i<2; i++) { + UE->dlsch[sf][0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); - if (!UE->dlsch[0][i]) { - printf("Can't get ue dlsch structures\n"); - exit(-1); - } + if (!UE->dlsch[sf][0][i]) { + printf("Can't get ue dlsch structures\n"); + exit(-1); + } - UE->dlsch[0][i]->rnti = n_rnti; + UE->dlsch[sf][0][i]->rnti = n_rnti; + } } + UE->dlsch_SI[0] = new_ue_dlsch(1,1,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->dlsch_ra[0] = new_ue_dlsch(1,1,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); + // structure for SIC at UE UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms); @@ -2177,6 +2197,7 @@ int main(int argc, char **argv) while ((!feof(input_trch_fd)) && (i<input_buffer_length0<<3)) { ret=fscanf(input_trch_fd,"%s",input_trch_val); + if (ret != 1) printf("ERROR: error reading file\n"); if (input_trch_val[0] == '1') input_buffer0[k][i>>3]+=(1<<(7-(i&7))); @@ -2233,7 +2254,10 @@ int main(int argc, char **argv) round_trials[2] = 0; round_trials[3] = 0; - dci_errors=0; + dci_errors[0]=0; + dci_errors[1]=0; + dci_errors[2]=0; + dci_errors[3]=0; // avg_ber = 0; round=0; @@ -2249,12 +2273,13 @@ int main(int argc, char **argv) reset_meas(&eNB->dlsch_rate_matching_stats); reset_meas(&eNB->dlsch_turbo_encoding_stats); - reset_meas(&UE->phy_proc_rx); // total UE rx + reset_meas(&UE->phy_proc_rx[subframe&0x1]); // total UE rx reset_meas(&UE->ofdm_demod_stats); reset_meas(&UE->dlsch_channel_estimation_stats); reset_meas(&UE->dlsch_freq_offset_estimation_stats); reset_meas(&UE->rx_dft_stats); - reset_meas(&UE->dlsch_decoding_stats); + reset_meas(&UE->dlsch_decoding_stats[0]); + reset_meas(&UE->dlsch_decoding_stats[1]); reset_meas(&UE->dlsch_turbo_decoding_stats); reset_meas(&UE->dlsch_deinterleaving_stats); reset_meas(&UE->dlsch_rate_unmatching_stats); @@ -2300,10 +2325,10 @@ int main(int argc, char **argv) // printf("Trial %d, round %d\n",trials,round); round_trials[round]++; - if(transmission_mode>=5) - pmi_feedback=1; - else - pmi_feedback=0; + //if(transmission_mode>=5) + // pmi_feedback=1; + //else + // pmi_feedback=0; if (abstx) { if (trials==0 && round==0 && SNR==snr0) //generate a new channel @@ -2335,7 +2360,7 @@ int main(int argc, char **argv) TB0_active = 1; eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3; - + fill_DCI(eNB,&dci_alloc[0],subframe,n_rnti,n_users,transmission_mode,common_flag,DLSCH_RB_ALLOC,TPC,mcs1,mcs2,trials&1,round&3,&num_common_dci,&num_ue_spec_dci,&num_dci); } else { @@ -2343,14 +2368,14 @@ int main(int argc, char **argv) (TB0_active==1)?mcs1:0,mcs2,trials&1,(TB0_active==1)?round&3:0,&num_common_dci,&num_ue_spec_dci,&num_dci); } for (i=num_common_dci; i<num_dci; i++) { - + dci_alloc[i].firstCCE = get_nCCE_offset_l1(CCE_table, 1<<dci_alloc[i].L, numCCE, (dci_alloc[i].rnti==SI_RNTI)? 1 : 0, dci_alloc[i].rnti, subframe); - + if (dci_alloc[i].firstCCE < 0) { printf("firstCCE <0 !! dci %d: rnti %x, format %d : nCCE %d/%d\n",i,dci_alloc[i].rnti, dci_alloc[i].format, dci_alloc[i].firstCCE,numCCE); @@ -2362,7 +2387,7 @@ int main(int argc, char **argv) } } // common_flag == 0 - + /* @@ -2389,22 +2414,22 @@ int main(int argc, char **argv) tx_lev_dB = (unsigned int) dB_fixed(tx_lev); } */ - + proc_eNB->subframe_tx = subframe; eNB->abstraction_flag=0; - + phy_procedures_eNB_TX(eNB,proc_eNB,no_relay,NULL,1); - - + + start_meas(&eNB->ofdm_mod_stats); - + /* do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], eNB->common_vars.txdata[eNB_id], (subframe*2), &eNB->frame_parms); - + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], eNB->common_vars.txdata[eNB_id], (subframe*2)+1, @@ -2425,19 +2450,19 @@ int main(int argc, char **argv) stop_meas(&eNB->ofdm_mod_stats); - + // generate next subframe for channel estimation - + proc_eNB->subframe_tx = subframe+1; - + phy_procedures_eNB_TX(eNB,proc_eNB,no_relay,NULL,0); - + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], eNB->common_vars.txdata[eNB_id], (subframe*2)+2, &eNB->frame_parms); - + proc_eNB->frame_tx++; tx_lev = 0; @@ -2450,7 +2475,7 @@ int main(int argc, char **argv) tx_lev_dB = (unsigned int) dB_fixed(tx_lev); - + if (n_frames==1) { printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB); @@ -2466,7 +2491,7 @@ int main(int argc, char **argv) } DL_channel(eNB,UE,subframe,awgn_flag,SNR,tx_lev,hold_channel,abstx,num_rounds,trials,round,eNB2UE,s_re,s_im,r_re,r_im,csv_fd); - + UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[subframe&1]; proc->subframe_rx = subframe; @@ -2479,16 +2504,19 @@ int main(int argc, char **argv) UE->rx_offset, 0, 0); - + if (n_frames==1) printf("Running phy_procedures_UE_RX\n"); phy_procedures_UE_RX(UE,proc,0,0,normal_txrx,no_relay,NULL); - if (UE->dlsch[0][0]->active == 0) { + if (UE->dlsch[subframe&0x1][0][0]->active == 0) { //printf("DCI not received\n"); + dci_errors[round]++; + UE->dlsch_errors[0] = 1; + /* write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],12*UE->frame_parms.N_RB_DL*3,1,1); - + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*12*UE->frame_parms.N_RB_DL,1,1); write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,12*UE->frame_parms.N_RB_DL*4*2,1,4); write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], @@ -2503,90 +2531,92 @@ int main(int argc, char **argv) if ((test_perf ==0 ) && (n_frames==1)) { write_output("ch0.m","ch0",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8); - + if (eNB->frame_parms.nb_antennas_tx>1) write_output("ch1.m","ch1",eNB2UE[0]->ch[eNB->frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8); - + //common vars write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); + write_output("rxsigF0.m","rxsF0", &UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - + if (UE->frame_parms.nb_antennas_rx>1) { write_output("rxsig1.m","rxs1", UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); write_output("rxsigF1.m","rxsF1", UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); } - + write_output("dlsch00_r0.m","dl00_r0", &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][0][0]), UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - + if (UE->frame_parms.nb_antennas_rx>1) write_output("dlsch01_r0.m","dl01_r0", &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][1][0]), UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - + if (eNB->frame_parms.nb_antennas_tx>1) write_output("dlsch10_r0.m","dl10_r0", &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2][0]), UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - + if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) write_output("dlsch11_r0.m","dl11_r0", &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][3][0]), UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); - + //pdsch_vars - dump_dlsch2(UE,eNB_id,subframe,coded_bits_per_codeword,round); - //dump_dlsch2(UE,eNB_id_i,coded_bits_per_codeword); + + dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[subframe&0x1][0][0]->current_harq_pid); + write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); - + //pdcch_vars - write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); - write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); - - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,2400,1,4); - + write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[0][eNB_id]->rxdataF_comp[0],4*300,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[0][eNB_id]->llr,2400,1,4); + } - - + + if (UE->dlsch_errors[0] == 0) { - avg_iter += UE->dlsch[eNB_id][0]->last_iteration_cnt; + avg_iter += UE->dlsch[subframe&0x1][eNB_id][0]->last_iteration_cnt; iter_trials++; if (n_frames==1) printf("No DLSCH errors found (round %d),uncoded ber %f\n",round,uncoded_ber); - UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->TBS; + UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->TBS; TB0_active = 0; - + } // DLSCH received ok else { errs[round]++; - avg_iter += UE->dlsch[eNB_id][0]->last_iteration_cnt-1; + avg_iter += UE->dlsch[subframe&0x1][eNB_id][0]->last_iteration_cnt-1; iter_trials++; if (n_frames==1) { //if ((n_frames==1) || (SNR>=30)) { printf("DLSCH errors found (round %d), uncoded ber %f\n",round,uncoded_ber); - for (s=0; s<UE->dlsch[0][0]->harq_processes[0]->C; s++) { - if (s<UE->dlsch[0][0]->harq_processes[0]->Cminus) - Kr = UE->dlsch[0][0]->harq_processes[0]->Kminus; + for (s=0; s<UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->C; s++) { + if (s<UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Cminus) + Kr = UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kminus; else - Kr = UE->dlsch[0][0]->harq_processes[0]->Kplus; + Kr = UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kplus; Kr_bytes = Kr>>3; printf("Decoded_output (Segment %d):\n",s); for (i=0; i<Kr_bytes; i++) - printf("%d : %x (%x)\n",i,UE->dlsch[0][0]->harq_processes[0]->c[s][i],UE->dlsch[0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]); + printf("%d : %x (%x)\n",i,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->c[s][i],UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]); } sprintf(fname,"rxsig0_r%d.m",round); @@ -2594,8 +2624,9 @@ int main(int argc, char **argv) write_output(fname,vname, &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); sprintf(fname,"rxsigF0_r%d.m",round); sprintf(vname,"rxs0F_r%d",round); + write_output(fname,vname, &UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - + if (UE->frame_parms.nb_antennas_rx>1) { sprintf(fname,"rxsig1_r%d.m",round); sprintf(vname,"rxs1_r%d.m",round); @@ -2636,26 +2667,27 @@ int main(int argc, char **argv) } //pdsch_vars - dump_dlsch2(UE,eNB_id,subframe,coded_bits_per_codeword,round); - + dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[subframe&0x1][0][0]->current_harq_pid); + + //write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); //write_output("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); //write_output("dlsch_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4); - //write_output("dlsch_w.m","w",UE->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); + //write_output("dlsch_w.m","w",UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); //pdcch_vars - write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); - write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); - - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,2400,1,4); - + write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[0][eNB_id]->rxdataF_comp[0],4*300,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[0][eNB_id]->llr,2400,1,4); + if (round == 3) exit(-1); } // printf("round %d errors %d/%d\n",round,errs[round],trials); round++; - // UE->dlsch[0][0]->harq_processes[0]->round++; + // UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->round++; } if (xforms==1) { @@ -2696,10 +2728,10 @@ int main(int argc, char **argv) double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx = (double)UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; + double t_rx = (double)UE->phy_proc_rx[subframe&0x1].p_time/cpu_freq_GHz/1000.0; double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx_dec = (double)UE->dlsch_decoding_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_dec = (double)UE->dlsch_decoding_stats[subframe&1].p_time/cpu_freq_GHz/1000.0; if (t_tx > t_tx_max) t_tx_max = t_tx; @@ -2819,13 +2851,13 @@ int main(int argc, char **argv) double std_phy_proc_rx_demod=0; double std_phy_proc_rx_dec=0; - effective_rate = ((double)(round_trials[0]-dci_errors)/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3])); + effective_rate = 1.0-((double)(errs[0]+errs[1]+errs[2]+errs[3])/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3])); printf("\n**********************SNR = %f dB (tx_lev %f)**************************\n", SNR, (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12))); - printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f (%2.1f%%,%f, %f), normalized delay %f (%f)\n", + printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f, normalized delay %f (%f)\n", errs[0], errs2[0], round_trials[0], @@ -2839,13 +2871,13 @@ int main(int argc, char **argv) (double)errs[1]/(round_trials[0]), (double)errs[2]/(round_trials[0]), (double)errs[3]/(round_trials[0]), - dci_errors, - round_trials[0], - (double)dci_errors/(round_trials[0]), - rate*effective_rate, + dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3], + round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3], + (double)(dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3])/(round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3]), + //rate*effective_rate, 100*effective_rate, - rate, - rate*get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs), + //rate, + //rate*get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); @@ -2885,10 +2917,10 @@ int main(int argc, char **argv) eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials); printf("\n\nUE RX function statistics (per 1ms subframe)\n\n"); - std_phy_proc_rx = sqrt((double)UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/UE->phy_proc_rx.trials - pow((double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0, - UE->phy_proc_rx.trials*2/3); + std_phy_proc_rx = sqrt((double)UE->phy_proc_rx[subframe&0x1].diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->phy_proc_rx[subframe&0x1].trials - pow((double)UE->phy_proc_rx[subframe&0x1].diff/UE->phy_proc_rx[subframe&0x1].trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx[subframe&0x1].diff/UE->phy_proc_rx[subframe&0x1].trials/cpu_freq_GHz/1000.0, + UE->phy_proc_rx[subframe&0x1].trials*2/3); printf("|__Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, @@ -2912,17 +2944,17 @@ int main(int argc, char **argv) printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3); printf("DLSCH unscrambling time :%f us (%d trials)\n",(double)UE->dlsch_unscrambling_stats.diff/UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0, UE->dlsch_unscrambling_stats.trials); - std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/UE->dlsch_decoding_stats.trials - pow((double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000,2)); + std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats[subframe&1].diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->dlsch_decoding_stats[subframe&1].trials - pow((double)UE->dlsch_decoding_stats[subframe&1].diff/UE->dlsch_decoding_stats[subframe&1].trials/cpu_freq_GHz/1000,2)); printf("DLSCH Decoding time (%02.2f Mbit/s, avg iter %1.2f) :%f us (%d trials, max %f)\n", eNB->dlsch[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter/iter_trials, - (double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats.trials, - (double)UE->dlsch_decoding_stats.max/cpu_freq_GHz/1000.0); + (double)UE->dlsch_decoding_stats[subframe&1].diff/UE->dlsch_decoding_stats[subframe&1].trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats[subframe&1].trials, + (double)UE->dlsch_decoding_stats[subframe&1].max/cpu_freq_GHz/1000.0); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3); printf("|__ DLSCH Rate Unmatching :%f us (%d trials)\n", (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials); printf("|__ DLSCH Turbo Decoding(%d bits) :%f us (%d trials)\n", - UE->dlsch[0][0]->harq_processes[0]->Cminus ? UE->dlsch[0][0]->harq_processes[0]->Kminus : UE->dlsch[0][0]->harq_processes[0]->Kplus, + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Cminus ? UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kminus : UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kplus, (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials); printf(" |__ init %f us (cycles/iter %f, %d trials)\n", (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, @@ -2968,7 +3000,7 @@ int main(int argc, char **argv) round_trials[2], errs[3], round_trials[3], - dci_errors); + dci_errors[0]); } else { fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n", SNR, @@ -2984,7 +3016,7 @@ int main(int argc, char **argv) round_trials[2], errs[3], round_trials[3], - dci_errors); + dci_errors[0]); } @@ -3017,7 +3049,7 @@ int main(int argc, char **argv) round_trials[2], errs[3], round_trials[3], - dci_errors); + dci_errors[0]); //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", @@ -3040,9 +3072,9 @@ int main(int argc, char **argv) (double)errs[1]/(round_trials[0]), (double)errs[2]/(round_trials[0]), (double)errs[3]/(round_trials[0]), - dci_errors, + dci_errors[0], round_trials[0], - (double)dci_errors/(round_trials[0]), + (double)dci_errors[0]/(round_trials[0]), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); @@ -3061,7 +3093,7 @@ int main(int argc, char **argv) round_trials[2], errs[3], round_trials[3], - dci_errors); + dci_errors[0]); //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", @@ -3085,9 +3117,9 @@ int main(int argc, char **argv) (double)errs[1]/(round_trials[0]), (double)errs[2]/(round_trials[0]), (double)errs[3]/(round_trials[0]), - dci_errors, + dci_errors[0], round_trials[0], - (double)dci_errors/(round_trials[0]), + (double)dci_errors[0]/(round_trials[0]), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); @@ -3100,12 +3132,12 @@ int main(int argc, char **argv) eNB->dlsch_modulation_stats.trials, eNB->dlsch_scrambling_stats.trials, eNB->dlsch_encoding_stats.trials, - UE->phy_proc_rx.trials, + UE->phy_proc_rx[subframe&0x1].trials, UE->ofdm_demod_stats.trials, UE->dlsch_rx_pdcch_stats.trials, UE->dlsch_llr_stats.trials, UE->dlsch_unscrambling_stats.trials, - UE->dlsch_decoding_stats.trials + UE->dlsch_decoding_stats[subframe&1].trials ); fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;", get_time_meas_us(&eNB->phy_proc_tx), @@ -3113,12 +3145,12 @@ int main(int argc, char **argv) get_time_meas_us(&eNB->dlsch_modulation_stats), get_time_meas_us(&eNB->dlsch_scrambling_stats), get_time_meas_us(&eNB->dlsch_encoding_stats), - get_time_meas_us(&UE->phy_proc_rx), + get_time_meas_us(&UE->phy_proc_rx[subframe&0x1]), nsymb*get_time_meas_us(&UE->ofdm_demod_stats), get_time_meas_us(&UE->dlsch_rx_pdcch_stats), 3*get_time_meas_us(&UE->dlsch_llr_stats), get_time_meas_us(&UE->dlsch_unscrambling_stats), - get_time_meas_us(&UE->dlsch_decoding_stats) + get_time_meas_us(&UE->dlsch_decoding_stats[subframe&1]) ); //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n"); fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); @@ -3153,12 +3185,12 @@ int main(int argc, char **argv) eNB->dlsch_modulation_stats.trials, eNB->dlsch_scrambling_stats.trials, eNB->dlsch_encoding_stats.trials, - UE->phy_proc_rx.trials, + UE->phy_proc_rx[subframe&0x1].trials, UE->ofdm_demod_stats.trials, UE->dlsch_rx_pdcch_stats.trials, UE->dlsch_llr_stats.trials, UE->dlsch_unscrambling_stats.trials, - UE->dlsch_decoding_stats.trials); + UE->dlsch_decoding_stats[subframe&1].trials); */ printf("[passed] effective rate : %f (%2.1f%%,%f)): log and break \n",rate*effective_rate, 100*effective_rate, rate ); break; @@ -3211,7 +3243,7 @@ int main(int argc, char **argv) printf("eNB %d\n",i); free_eNB_dlsch(eNB->dlsch[0][i]); printf("UE %d\n",i); - free_ue_dlsch(UE->dlsch[0][i]); + free_ue_dlsch(UE->dlsch[subframe&0x1][0][i]); } diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c new file mode 100644 index 0000000000000000000000000000000000000000..57742c5e13e4ec8d1f7fe13e0fe069a7ce1238c4 --- /dev/null +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c @@ -0,0 +1,5354 @@ +/* + * 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.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.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 dlsim.c + \brief Top-level DL simulator + \author R. Knopp + \date 2011 - 2014 + \version 0.1 + \company Eurecom + \email: knopp@eurecom.fr + \note + \warning +*/ + +//#define DEBUG_HARQ +//#define PRINT_THROUGHPUT + +#include <string.h> +#include <math.h> +#include <unistd.h> +#include <execinfo.h> +#include <signal.h> + +#include <stdbool.h> +#include "SIMULATION/TOOLS/defs.h" +#include "PHY/types.h" +#include "PHY/defs.h" +#include "PHY/vars.h" + +#include "SCHED/defs.h" +#include "SCHED/vars.h" +#include "LAYER2/MAC/vars.h" +#include "OCG_vars.h" +#include "UTIL/LOG/log.h" +#include "UTIL/LISTS/list.h" + +#include "unitary_defs.h" + +extern unsigned int dlsch_tbs25[27][25],TBStable[27][110]; +extern unsigned char offset_mumimo_llr_drange_fix; + +extern uint8_t interf_unaw_shift0; +extern uint8_t interf_unaw_shift1; +extern uint8_t interf_unaw_shift; + +#include "PHY/TOOLS/lte_phy_scope.h" + +#define PRINT_BYTES + +PHY_VARS_eNB *eNB; +PHY_VARS_UE *UE; + +double cpuf; + +int otg_enabled=0; +/*the following parameters are used to control the processing times calculations*/ +double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */ +double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */ +double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */ +double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */ +int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ +int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ + +void handler(int sig) +{ + void *array[10]; + size_t size; + + // get void*'s for all entries on the stack + size = backtrace(array, 10); + + // print out all the frames to stderr + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, 2); + exit(1); +} + + + +//DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_2A[2]; + +DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_1E[2]; +uint64_t DLSCH_alloc_pdu_1[2]; + +#define UL_RB_ALLOC 0x1ff; +#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2) + +//#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 +//#define DLSCH_RB_ALLOC 0x0001 +void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms) +{ + + int aa, slot_offset, slot_offset_F; + + slot_offset_F = (next_slot)*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7); + slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); + + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + // printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc()); + + if (frame_parms->Ncp == 1) + PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input + &txdata[aa][slot_offset], // output + frame_parms->ofdm_symbol_size, + 6, // number of symbols + frame_parms->nb_prefix_samples, // number of prefix samples + CYCLIC_PREFIX); + else { + normal_prefix_mod(&txdataF[aa][slot_offset_F], + &txdata[aa][slot_offset], + 7, + frame_parms); + } + + + } + +} + +int main(int argc, char **argv) +{ + + int c; + int k,i,aa,aarx,aatx; + + int s,Kr,Kr_bytes; + + double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1,rate[2]; + double snr_step=1,input_snr_step=1, snr_int=30; + + LTE_DL_FRAME_PARMS *frame_parms; + double **s_re,**s_im,**r_re,**r_im; + double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel + double iqim=0.0; + + uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1, n_tx_phy=1, n_rx=1; + uint16_t Nid_cell=0; + + int8_t eNB_id = 0, eNB_id_i = 1; + unsigned char mcs1=0,mcs2=0,mcs_i=0,awgn_flag=0,dci_flag=0; + unsigned char i_mod = 2; + unsigned short NB_RB; + unsigned char Ns,l,m; + uint16_t tdd_config=3; + uint16_t n_rnti=0x1234; + int n_users = 1; + + int TB=0; + RX_type_t rx_type=rx_standard; + unsigned char cur_harq_pid; + int hold_rank1_precoder=0; + int tpmi_retr=0; + bool is_first_time; + int updated_csi = 0; + + SCM_t channel_model=Rayleigh1; + // unsigned char *input_data,*decoded_output; + + unsigned char *input_buffer0[2],*input_buffer1[2]; + unsigned short input_buffer_length0,input_buffer_length1; + + /* A variable "ret" is a nuumber of turbo iterations, that are performed in the turbo-decoder for each CW. + The decoder checks CRC, and if CRC test fails, it increments "ret". Ret is between 1 and 4, where 4 is for + the max number of turbo iterations. If the CRC is passed, ret is equal to a current iteration. + This is done separately for each CW inside decoding process. + Again: this is not a HARQ retransmission!*/ + unsigned int ret[2]; + unsigned int coded_bits_per_codeword[2],nsymb,dci_cnt,tbs[2]; + + unsigned int tx_lev=0, tx_lev_dB=0, round=0, trials, errs[2][4]={{0,0,0,0},{0,0,0,0}}, round_trials[2][4]={{0,0,0,0},{0,0,0,0}}, decoded_in_sic[4]={0,0,0,0}, sic_attempt[4]={0,0,0,0}, round_sic=0; + unsigned int dci_errors=0, dlsch_active=0; + unsigned int resend_one[4]={0,0,0,0}, resend_both[4]={0,0,0,0}, TB0_deact[4]={0,0,0,0}, TB1_deact[4]={0,0,0,0}; + + int re_allocated; + char fname[32],vname[32]; + FILE *bler_fd; + char bler_fname[256]; + FILE *time_meas_fd; + char time_meas_fname[256]; + + FILE *input_trch_fd=NULL; + unsigned char input_trch_file=0; + FILE *input_fd=NULL; + unsigned char input_file=0; + // char input_val_str[50],input_val_str2[50]; + + char input_trch_val[16]; + double channelx,channely; + + // unsigned char pbch_pdu[6]; + + DCI_ALLOC_t dci_alloc[8],dci_alloc_rx[8]; + int num_common_dci=0,num_ue_spec_dci=0,num_dci=0; + + // FILE *rx_frame_file; + + int n_frames; + int n_ch_rlz = 1; + + channel_desc_t *eNB2UE[8]; + + uint8_t num_pdcch_symbols=1,num_pdcch_symbols_2=0; + uint8_t pilot1,pilot2,pilot3; + uint8_t rx_sample_offset = 0; + //char stats_buffer[4096]; + //int len; + + uint8_t num_rounds = 4; + uint8_t subframe=7; + int u; + int n=0; + int abstx=0; + int iii; + FILE *csv_fd=NULL; + char csv_fname[512]; + int ch_realization; + int pmi_feedback=0; + int hold_channel=0; + + // temporarily for retransmissions: + unsigned char resend_cw1=0; //if 0 resend only cw0 + unsigned char resend_cw0_cw1=1; //if 0 resend both cw in a normal way + + // void *data; + // int ii; + int bler; + double blerr[2][4],uncoded_ber,avg_ber; + short *uncoded_ber_bit=NULL; + uint8_t N_RB_DL=25,osf=1; + uint8_t fdd_flag = 0; + frame_t frame_type = FDD; + int xforms=0; + FD_lte_phy_scope_ue *form_ue = NULL; + char title[255]; + uint32_t DLSCH_RB_ALLOC = 0x1fff; + int numCCE=0; + int dci_length_bytes=0,dci_length=0; + int common_flag=0,TPC=0; + + double cpu_freq_GHz; + //time_stats_t ts;//,sts,usts; + int avg_iter[2],iter_trials[2]; + int rballocset=0; + int print_perf=0; + int test_perf=0; + int dump_table=0; + int llr8_flag=0; + + double effective_rate=0.0; + + double thr_cw0_tm4 = 0.0; + double thr_cw0_tm4_nonconst = 0.0; + double thr_cw0[4]={0,0,0,0}, thr_cw1[4]={0,0,0,0}, thr_cw0_tot = 0.0, thr_cw1_tot = 0.0; + unsigned int tbs0_init=0, tbs1_init=0; + double rate0_init=0.0, rate1_init=0.0; + int mcs0_init=0, mcs1_init=0, mod_order0_init = 0, mod_order1_init=0; + char channel_model_input[17]="I"; + + int TB0_active = 1; + int TB1_active = 1; + + uint32_t perfect_ce = 0; + + LTE_DL_UE_HARQ_t *dlsch0_ue_harq; + LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq; + uint8_t Kmimo; + + int32_t **sic_buffer; + int8_t cw_to_decode_interf; + int8_t cw_to_decode_interf_free; + int8_t cw_non_sic; + int8_t cw_sic; + FILE *proc_fd = NULL; + char buf[64]; + uint8_t ue_category=4; + uint32_t Nsoft; + + int CCE_table[800]; + + int threequarter_fs=0; + + opp_enabled=1; // to enable the time meas + +#if defined(__arm__) + FILE *proc_fd = NULL; + char buf[64]; + + proc_fd = fopen("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq", "r"); + if(!proc_fd) + printf("cannot open /sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq"); + else { + while(fgets(buf, 63, proc_fd)) + printf("%s", buf); + } + fclose(proc_fd); + cpu_freq_GHz = ((double)atof(buf))/1e6; +#else + cpu_freq_GHz = get_cpu_freq_GHz(); +#endif + cpuf = cpu_freq_GHz; + + printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz); + + //signal(SIGSEGV, handler); + //signal(SIGABRT, handler); + + logInit(); + set_glog(LOG_INFO, LOG_MED); + + // default parameters + n_frames = 1000; + snr0 = 0; + // num_layers = 1; + perfect_ce = 0; + + + while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:XYv:W:J:K:U")) != -1) { + + switch (c) { + case 'a': + awgn_flag = 1; + channel_model = AWGN; + break; + + case 'A': + abstx = 1; + break; + + case 'b': + tdd_config=atoi(optarg); + break; + + case 'B': + N_RB_DL=atoi(optarg); + break; + + case 'c': + num_pdcch_symbols=atoi(optarg); + break; + + case 'C': + Nid_cell = atoi(optarg); + break; + + case 'd': + dci_flag = 1; + break; + + case 'D': + frame_type=TDD; + break; + + case 'e': + num_rounds=1; + common_flag = 1; + TPC = atoi(optarg); + break; + + case 'E': + threequarter_fs=1; + break; + + case 'f': + input_snr_step= atof(optarg); + break; + + case 'F': + forgetting_factor = atof(optarg); + break; + + case 'i': + input_fd = fopen(optarg,"r"); + input_file=1; + dci_flag = 1; + break; + + case 'I': + input_trch_fd = fopen(optarg,"r"); + input_trch_file=1; + break; + + case 'L': + llr8_flag=1; + break; + + case 'l': + offset_mumimo_llr_drange_fix=atoi(optarg); + break; + + case 'm': + mcs1 = atoi(optarg); + break; + + case 'M': + mcs2 = atoi(optarg); + //i_mod = get_Qm(mcs2); /// think here again!!! + break; + + case 'O': + test_perf=atoi(optarg); + //print_perf =1; + break; + + case 't': + mcs_i = atoi(optarg); + i_mod = get_Qm(mcs_i); + break; + + case 'n': + n_frames = atoi(optarg); + break; + + case 'o': + rx_sample_offset = atoi(optarg); + break; + + case 'r': + DLSCH_RB_ALLOC = atoi(optarg); + rballocset = 1; + break; + + case 's': + snr0 = atof(optarg); + break; + + case 'w': + snr_int = atof(optarg); + break; + + case 'N': + n_ch_rlz= atof(optarg); + break; + + case 'p': + extended_prefix_flag=1; + break; + + case 'g': + memcpy(channel_model_input,optarg,17); + + switch((char)*optarg) { + case 'A': + channel_model=SCM_A; + break; + case 'B': + channel_model=SCM_B; + break; + case 'C': + channel_model=SCM_C; + break; + case 'D': + channel_model=SCM_D; + break; + case 'E': + channel_model=EPA; + break; + case 'F': + channel_model=EVA; + break; + case 'G': + channel_model=ETU; + break; + case 'H': + channel_model=Rayleigh8; + break; + case 'I': + channel_model=Rayleigh1; + break; + case 'J': + channel_model=Rayleigh1_corr; + break; + case 'K': + channel_model=Rayleigh1_anticorr; + break; + case 'L': + channel_model=Rice8; + break; + case 'M': + channel_model=Rice1; + break; + case 'N': + channel_model=AWGN; + break; + case 'P': + channel_model=Rayleigh1_orthogonal; + break; + case 'Q': + channel_model=Rayleigh1_orth_eff_ch_TM4_prec_real; // for DUALSTREAM_UNIFORM_PRECODING1 when interf is precancelled + break; + case 'R': + channel_model=Rayleigh1_orth_eff_ch_TM4_prec_imag; // for DUALSTREAM_UNIFORM_PRECODINGj when interf is precancelled + break; + case 'S': + channel_model=Rayleigh8_orth_eff_ch_TM4_prec_real;//when interf is precancelled + break; + case 'T': + channel_model=Rayleigh8_orth_eff_ch_TM4_prec_imag;//when interf is precancelled + break; + case 'U': + channel_model = TS_SHIFT; + break; + case 'V': + channel_model=EPA_low; + break; + case 'W': + channel_model=EPA_medium; + break; + case 'X': + channel_model=EPA_high; + break; + default: + msg("Unsupported channel model!\n"); + exit(-1); + } + break; + case 'z': + n_rx=atoi(optarg); + if ((n_rx==0) || (n_rx>2)) { + msg("Unsupported number of rx antennas %d\n",n_rx); + exit(-1); + } + break; + + case 'R': + num_rounds=atoi(optarg); + break; + case 'S': + subframe=atoi(optarg); + break; + case 'T': + n_rnti=atoi(optarg); + break; + case 'u': + rx_type = (RX_type_t) atoi(optarg); + if (rx_type<rx_standard || rx_type>rx_SIC_dual_stream) { + printf("Unsupported rx type %d\n",rx_type); + exit(-1); + } + break; + case 'v': + i_mod = atoi(optarg); + if (i_mod!=2 && i_mod!=4 && i_mod!=6) { + msg("Wrong i_mod %d, should be 2,4 or 6\n",i_mod); + exit(-1); + } + break; + case 'P': + print_perf=1; + break; + case 'q': + n_tx_port=atoi(optarg); + + if ((n_tx_port==0) || ((n_tx_port>2))) { + msg("Unsupported number of cell specific antennas ports %d\n",n_tx_port); + exit(-1); + } + break; + case 'x': + transmission_mode=atoi(optarg); + if ((transmission_mode!=1) && + (transmission_mode!=2) && + (transmission_mode!=3) && + (transmission_mode!=4) && + (transmission_mode!=5) && + (transmission_mode!=6)) { + msg("Unsupported transmission mode %d\n",transmission_mode); + exit(-1); + } + if (transmission_mode>1 && transmission_mode<7) { + n_tx_port = 2; + } + break; + case 'y': + n_tx_phy=atoi(optarg); + + if (n_tx_phy < n_tx_port) { + msg("n_tx_phy mush not be smaller than n_tx_port"); + exit(-1); + } + + if ((transmission_mode>1 && transmission_mode<7) && n_tx_port<2) { + msg("n_tx_port must be >1 for transmission_mode %d\n",transmission_mode); + exit(-1); + } + + if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) { + msg("Physical number of antennas not supported for TM7.\n"); + exit(-1); + } + + break; + case 'X': + xforms = 1; + break; + case 'Z': + dump_table=1; + break; + case 'Y': + perfect_ce=1; + break; + case 'V': + interf_unaw_shift0=atoi(optarg); + break; + case 'W': + interf_unaw_shift1=atoi(optarg); + break; + case 'J': + interf_unaw_shift=atoi(optarg); + break; + case 'K': + tpmi_retr = atoi(optarg); + break; + case 'U': + updated_csi=1; + break; + case 'h': + default: + printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,3,5,6) -y TXant -z RXant -I trch_file\n",argv[0]); + printf("-h This message\n"); + printf("-a Use AWGN channel and not multipath\n"); + printf("-c Number of PDCCH symbols\n"); + printf("-m MCS1 for TB 1\n"); + printf("-M MCS2 for TB 2\n"); + printf("-d Transmit the DCI and compute its error statistics and the overall throughput\n"); + printf("-p Use extended prefix mode\n"); + printf("-n Number of frames to simulate\n"); + printf("-o Sample offset for receiver\n"); + printf("-s Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated\n", snr_int, snr_step); + printf("-f step size of SNR, default value is 1.\n"); + printf("-r resource block allocation (see section 7.1.6.3 in 36.213\n"); + printf("-g Channel model, possible values are 3GPP 25.814 SCM-A/B/C/D('A','B','C','D'), 36-101 EPA('E'), EVA ('F'),ETU('G'), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr('K'), Rice8('L'), Rice1('M'), AWGN('N'), Rayleigh1_orthogonal('P'), Rayleigh1_orth_eff_ch_TM4_prec_real ('Q'), Rayleigh1_orth_eff_ch_TM4_prec_imag ('R'), Rayleigh8_orth_eff_ch_TM4_prec_real ('S'),Rayleigh8_orth_eff_ch_TM4_prec_imag ('T'), EPA_low ('V'), EPA_medium ('W'), EPA_high ('X') \n"); + printf("-F forgetting factor (0 new channel every trial, 1 channel constant\n"); + printf("-x Transmission mode (1,2,6 for the moment)\n"); + printf("-y Number of TX antennas used in eNB\n"); + printf("-z Number of RX antennas used in UE\n"); + printf("-t MCS of interfering UE\n"); + printf("-R Number of HARQ rounds (fixed)\n"); + printf("-A Turns on calibration mode for abstraction.\n"); + printf("-N Determines the number of Channel Realizations in Abstraction mode. Default value is 1. \n"); + printf("-O Set the percentage of effective rate to testbench the modem performance (typically 30 and 70, range 1-100) \n"); + printf("-I Input filename for TrCH data (binary)\n"); + printf("-u Receiver type: 0=standard, 1 = single stream IC (for TM3,4,5,6), 2 = dual stream IC (for TM3,4), 3 = SIC (for TM3,4) \n"); + exit(1); + break; + + } + } + + if (common_flag == 0) { + switch (N_RB_DL) { + case 6: + if (rballocset==0) DLSCH_RB_ALLOC = 0x3f; + num_pdcch_symbols = 3; + break; + + case 25: + if (rballocset==0) DLSCH_RB_ALLOC = 0x1fff; + break; + + case 50: + if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffff; + break; + + case 100: + if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffffff; + break; + } + + NB_RB=conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL); + } else + NB_RB = 4; + + NB_RB=conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL); + + + if (((transmission_mode==1) || (transmission_mode==2)) && (rx_type != rx_standard)) { + printf("only standard rx available for TM1 and TM2\n"); + exit(-1); + } + if (((transmission_mode==5) || (transmission_mode==6)) && (rx_type > rx_IC_single_stream)) { + printf("only standard rx or single stream IC available for TM5 and TM6\n"); + exit(-1); + } + + + if (xforms==1) { + fl_initialize (&argc, argv, NULL, 0, 0); + form_ue = create_lte_phy_scope_ue(); + sprintf (title, "LTE PHY SCOPE eNB"); + fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + + /* + if (rx_type==rx_IC_single_stream) { + openair_daq_vars.use_ia_receiver = 1; + fl_set_button(form_ue->button_0,1); + fl_set_object_label(form_ue->button_0, "IA Receiver ON"); + fl_set_object_color(form_ue->button_0, FL_GREEN, FL_GREEN); + } + + */ + } + + if (transmission_mode==5) { + n_users = 2; + eNB_id_i = UE->n_connected_eNB; + //eNB_id_i=1; + } + else + eNB_id_i = eNB_id; + + lte_param_init(n_tx_port, + n_tx_phy, + n_rx, + transmission_mode, + extended_prefix_flag, + frame_type, + Nid_cell, + tdd_config, + N_RB_DL, + threequarter_fs, + osf, + perfect_ce); + + + printf("Setting mcs1 = %d\n",mcs1); + printf("Setting mcs2 = %d\n",mcs2); + printf("NPRB = %d\n",NB_RB); + printf("n_frames = %d\n",n_frames); + printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag); + printf("Using receiver type %d\n", rx_type); + printf("TM1 shift %d\n", interf_unaw_shift); + //printf("Using I_UA rec shift layer 1 %d\n", interf_unaw_shift0); + //printf("Using I_UA rec shift layer 2 %d\n", interf_unaw_shift1); + snr1 = snr0+snr_int; + printf("SNR0 %f, SNR1 %f\n",snr0,snr1); + + /* + txdataF = (int **)malloc16(2*sizeof(int*)); + txdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES); + txdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES); + + txdata = (int **)malloc16(2*sizeof(int*)); + txdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES); + txdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); + */ + + frame_parms = &eNB->frame_parms; + + + s_re = malloc(2*sizeof(double*)); //transmitted signal (Sent) + s_im = malloc(2*sizeof(double*)); + r_re = malloc(2*sizeof(double*)); //received signal + r_im = malloc(2*sizeof(double*)); + // r_re0 = malloc(2*sizeof(double*)); + // r_im0 = malloc(2*sizeof(double*)); + + nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; + + + printf("Channel Model= (%s,%d)\n",channel_model_input, channel_model); + printf("SCM-A=%d, SCM-B=%d, SCM-C=%d, SCM-D=%d, EPA=%d, EVA=%d, ETU=%d, Rayleigh8=%d, Rayleigh1=%d, Rayleigh1_corr=%d, Rayleigh1_anticorr=%d, Rice1=%d, Rice8=%d, Rayleigh1_orthogonal=%d, Rayleigh1_orth_eff_ch_TM4_prec_real22=%d, Rayleigh1_orth_eff_ch_TM4_prec_imag=%d, Rayleigh8_orth_eff_ch_TM4_prec_real=%d, Rayleigh8_orth_eff_ch_TM4_prec_imag=%d , TS_SHIFT=%d\n", + SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr, Rayleigh1_anticorr, Rice1, Rice8, Rayleigh1_orthogonal, Rayleigh1_orth_eff_ch_TM4_prec_real, Rayleigh1_orth_eff_ch_TM4_prec_imag, Rayleigh8_orth_eff_ch_TM4_prec_real, Rayleigh8_orth_eff_ch_TM4_prec_imag, TS_SHIFT); + if(transmission_mode==5) + sprintf(bler_fname,"bler_tx%d_rec%d_chan%d_nrx%d_mcs%d_mcsi%d_u%d_imod%d.csv",transmission_mode,rx_type,channel_model,n_rx,mcs1,mcs_i,rx_type,i_mod); + else if (abstx == 1){ + if (perfect_ce==1) + sprintf(bler_fname,"bler_tx%d_r%d_ch%d_%d_nrx%d_rnd%d_mcs%d_mcsi%d_ab_pce_sh%d_rpmi%d_n.csv",transmission_mode,rx_type,channel_model,n_frames, n_rx, num_rounds, mcs1, mcs2,interf_unaw_shift, tpmi_retr); + else + sprintf(bler_fname,"bler_tx%d_r%d_ch%d_%d_nrx%d_rnd%d_mcs%d_mcsi%d_ab_sh%d_rtpmi%d_n.csv",transmission_mode,rx_type,channel_model, n_frames, n_rx, num_rounds, mcs1, mcs2,interf_unaw_shift, tpmi_retr); + } + else {//abstx=0 + if (perfect_ce==1){ + if (updated_csi==1){ + sprintf(bler_fname,"bler_tx%d_r%d_ch%d_%d_nrx%d_rnd%d_mcs%d_mcsi%d_pce_sh%d_up_rtpmi%d_n.csv",transmission_mode,rx_type,channel_model,n_frames, n_rx, num_rounds, mcs1, mcs2, interf_unaw_shift, tpmi_retr); + } + else{ + sprintf(bler_fname,"bler_tx%d_r%d_ch%d_%d_nrx%d_rnd%d_mcs%d_mcsi%d_pce_sh%d_rtpmi%d_n.csv",transmission_mode,rx_type, channel_model,n_frames, n_rx, num_rounds, mcs1, mcs2, interf_unaw_shift, tpmi_retr); + } + } + else{ + if (updated_csi==1){ + sprintf(bler_fname,"bler_tx%d_r%d_ch%d_%d_nrx%d_rnd%d_mcs%d_mcsi%d_sh%d_up_rtpmi%d_n.csv",transmission_mode,rx_type,channel_model,n_frames, n_rx, num_rounds, mcs1, mcs2, interf_unaw_shift, tpmi_retr); + } + else{ + sprintf(bler_fname,"bler_tx%d_r%d_ch%d_%d_nrx%d_rnd%d_mcs%d_mcsi%d_sh%d_rtpmi%csv",transmission_mode,rx_type, channel_model,n_frames, n_rx, num_rounds, mcs1, mcs2, interf_unaw_shift, tpmi_retr); + } + } + } + + bler_fd = fopen(bler_fname,"w"); + if (bler_fd==NULL) { + fprintf(stderr,"Cannot create file %s!\n",bler_fname); + exit(-1); + } + + if ((transmission_mode != 3) && (transmission_mode != 4)) + fprintf(bler_fd,"SNR; MCS1; MCS2; TBS1; TBS2; rate 0; rate 1; err0_st1; err0_st2 trials0; err1_st1; err1_st2; trials1; err2_st1; err2_st2; trials2; err3_st1; err3_st2; trials3; throug 0; throug 1; sum throug; dci_err\n"); + else if (rx_type == rx_SIC_dual_stream) + fprintf(bler_fd,"SNR; MCS1; MCS2; TBS1; TBS2; rate 0; rate 1; err0_tb0; err0_tb1; trials_tb0_r0; trials_tb1_r0; sic_att0; sic_suc0; ret_both0; ret_one0; err1_tb0; err1_tb1; trials_tb0_r1; trials_tb1_r1; sic_att1; sic_suc1; ret_both1; ret_one1; err2_tb0; err2_tb1; trials_tb0_r2; trials1_tb1_r2; sic_att2; sic_suc2; ret_both2; ret_one2; err3_tb0; err3_tb1; trials_tb0_r3; trials_tb1_r3; sic_att3; sic_suc3; th_tb0_r0; th_tb1_r0; th_sum_r0; th_tb0_r1; th_tb1_r1; th_sum_r1; th_tb0_r2; th_tb1_r2; th_sum_r2; th_tb0_r3; th_tb1_r3; th_sum_r3; tot_th\n"); + else + fprintf(bler_fd,"SNR; MCS1; MCS2; TBS1; TBS2; rate 0; rate 1; err0_tb0; err0_tb1; trials_tb0_r0; trials_tb1_r0; deact_tb0_r0; deact_tb1_r0; ret_both0; ret_one0; err1_tb0; err1_tb1; trials_tb0_r1; trials_tb1_r1; deact_tb0_r1; deact_tb1_r1; ret_both1; ret_one1; err2_tb0; err2_tb1; trials_tb0_r2; trials1_tb1_r2; deact_tb0_r2; deact_tb1_r2; ret_both2; ret_one2; err3_tb0; err3_tb1; trials_tb0_r3; trials_tb1_r3; th_tb0_r0; th_tb1_r0; th_sum_r0; th_tb0_r1; th_tb1_r1; th_sum_r1; th_tb0_r2; th_tb1_r2; th_sum_r2; th_tb0_r3; th_tb1_r3; th_sum_r3; tot_th\n"); + + if (test_perf != 0) { + + char hostname[1024]; + + hostname[1023] = '\0'; + gethostname(hostname, 1023); + printf("Hostname: %s\n", hostname); + //char dirname[FILENAME_MAX]; + //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); + sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", + N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); + //mkdir(dirname,0777); + time_meas_fd = fopen(time_meas_fname,"w"); + if (time_meas_fd==NULL) { + fprintf(stderr,"Cannot create file %s!\n",time_meas_fname); + exit(-1); + } + } + + if(abstx){ + // CSV file // add here second stream mcs + + if (transmission_mode == 5) + sprintf(csv_fname,"dataout_tx%d_u2%d_mcs%d_chan%d_nsimus%d_R%d_abstr.m",transmission_mode,rx_type,mcs1,channel_model,n_frames,num_rounds); + + else + if (perfect_ce==1) + sprintf(csv_fname,"dout_tx%d_r%d_ch%d_%d_rnd%d_mcs%d_mcsi%d_pce_sh%d_%d_csi.m",transmission_mode,rx_type, channel_model, n_frames, num_rounds, mcs1, mcs2, interf_unaw_shift, n_ch_rlz); + else + sprintf(csv_fname,"dout_tx%d_r%d_ch%d_%d_rnd%d_mcs%d_mcsi%d_sh%d_%d_csi.m",transmission_mode,rx_type, channel_model, n_frames, num_rounds, mcs1, mcs2, interf_unaw_shift, n_ch_rlz); + + csv_fd = fopen(csv_fname,"w"); + fprintf(csv_fd,"data_all%d=[",mcs1); + if (csv_fd==NULL) { + fprintf(stderr,"Cannot create file %s!\n",csv_fname); + exit(-1); + } + } + + for (i=0; i<2; i++) { + s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + // r_re0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + // bzero(r_re0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + // r_im0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + // bzero(r_im0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); + } + + UE->pdcch_vars[subframe&0x1][0]->crnti = n_rnti; + UE->transmission_mode[eNB_id]=transmission_mode; + if (UE->transmission_mode[eNB_id] !=4) + UE->measurements.rank[eNB_id]=0; + else + UE->measurements.rank[eNB_id]=1; + + // Fill in UL_alloc + UL_alloc_pdu.type = 0; + UL_alloc_pdu.hopping = 0; + UL_alloc_pdu.rballoc = UL_RB_ALLOC; + UL_alloc_pdu.mcs = 1; + UL_alloc_pdu.ndi = 1; + UL_alloc_pdu.TPC = 0; + UL_alloc_pdu.cqi_req = 1; + + CCCH_alloc_pdu.type = 0; + CCCH_alloc_pdu.vrb_type = 0; + CCCH_alloc_pdu.rballoc = CCCH_RB_ALLOC; + CCCH_alloc_pdu.ndi = 1; + CCCH_alloc_pdu.mcs = 1; + CCCH_alloc_pdu.harq_pid = 0; + + DLSCH_alloc_pdu2_1E[0].rah = 0; + DLSCH_alloc_pdu2_1E[0].rballoc = DLSCH_RB_ALLOC; + DLSCH_alloc_pdu2_1E[0].TPC = 0; + DLSCH_alloc_pdu2_1E[0].dai = 0; + DLSCH_alloc_pdu2_1E[0].harq_pid = 0; + //DLSCH_alloc_pdu2_1E[0].tb_swap = 0; + DLSCH_alloc_pdu2_1E[0].mcs = mcs1; + DLSCH_alloc_pdu2_1E[0].ndi = 1; + DLSCH_alloc_pdu2_1E[0].rv = 0; + // Forget second codeword + DLSCH_alloc_pdu2_1E[0].tpmi = (transmission_mode>=5 ? 5 : 0); // precoding + DLSCH_alloc_pdu2_1E[0].dl_power_off = (transmission_mode==5 ? 0 : 1); + + DLSCH_alloc_pdu2_1E[1].rah = 0; + DLSCH_alloc_pdu2_1E[1].rballoc = DLSCH_RB_ALLOC; + DLSCH_alloc_pdu2_1E[1].TPC = 0; + DLSCH_alloc_pdu2_1E[1].dai = 0; + DLSCH_alloc_pdu2_1E[1].harq_pid = 0; + //DLSCH_alloc_pdu2_1E[1].tb_swap = 0; + DLSCH_alloc_pdu2_1E[1].mcs = mcs_i; + DLSCH_alloc_pdu2_1E[1].ndi = 1; + DLSCH_alloc_pdu2_1E[1].rv = 0; + // Forget second codeword + DLSCH_alloc_pdu2_1E[1].tpmi = (transmission_mode>=5 ? 5 : 0) ; // precoding + DLSCH_alloc_pdu2_1E[1].dl_power_off = (transmission_mode==5 ? 0 : 1); + + eNB2UE[0] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, + channel_model, + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + forgetting_factor, + rx_sample_offset, + 0); + + if(num_rounds>1) { + for(n=1; n<8; n++) + eNB2UE[n] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, + channel_model, + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + forgetting_factor, + rx_sample_offset, + 0); + } + + if (eNB2UE[0]==NULL) { + msg("Problem generating channel model. Exiting.\n"); + exit(-1); + } + + if ((transmission_mode == 3) || (transmission_mode==4) || (transmission_mode==8)) + Kmimo=2; + else + Kmimo=1; + + switch (ue_category) { + case 1: + Nsoft = 250368; + break; + case 2: + case 3: + Nsoft = 1237248; + break; + case 4: + Nsoft = 1827072; + break; + default: + printf("Unsupported UE category %d\n",ue_category); + exit(-1); + break; + } + + for (k=0; k<n_users; k++) { + // Create transport channel structures for 2 transport blocks (MIMO) + for (i=0; i<2; i++) { //i is a CW + eNB->dlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0, &eNB->frame_parms); + + if (!eNB->dlsch[k][i]) { + + printf("Can't get eNB dlsch structures\n"); + exit(-1); + } + + eNB->dlsch[k][i]->rnti = n_rnti+k; + } + } + + for (i=0; i<2; i++) { + UE->dlsch[subframe&0x1][0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + + if (!UE->dlsch[subframe&0x1][0][i]) { + + printf("Can't get ue dlsch structures\n"); + exit(-1); + } + + UE->dlsch[subframe&0x1][0][i]->rnti = n_rnti; + } + + // structure for SIC at UE + UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0, &eNB->frame_parms); + + if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { + + eNB->UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff); + + if (n_users>1) + eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); //opposite PMI + } else { + eNB->UE_stats[0].DL_pmi_single = 0; + + if (n_users>1) + eNB->UE_stats[1].DL_pmi_single = 0; + } + + + sic_buffer = (int32_t **) malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t *) ); + for (i=0; i<frame_parms->nb_antennas_tx; i++) { + sic_buffer[i] = malloc16_clear(FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + } + + if (input_fd==NULL) { + + // UE specific DCI + for(k=0; k<n_users; k++) { + switch(transmission_mode) { + case 1: + case 2: + if (common_flag == 0) { + + if (eNB->frame_parms.frame_type == TDD) { + + switch (eNB->frame_parms.N_RB_DL) { + + case 6: + dci_length = sizeof_DCI1_1_5MHz_TDD_t; + dci_length_bytes = sizeof(DCI1_1_5MHz_TDD_t); + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1_5MHz_TDD_t; + dci_length_bytes = sizeof(DCI1_5MHz_TDD_t); + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1_10MHz_TDD_t; + dci_length_bytes = sizeof(DCI1_10MHz_TDD_t); + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + dci_length = sizeof_DCI1_20MHz_TDD_t; + dci_length_bytes = sizeof(DCI1_20MHz_TDD_t); + break; + } + } + else { //fdd + + switch (eNB->frame_parms.N_RB_DL) { + + case 6: + dci_length = sizeof_DCI1_1_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1_1_5MHz_FDD_t); + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1_5MHz_FDD_t); + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1_10MHz_FDD_t; + dci_length_bytes = sizeof(DCI1_10MHz_FDD_t); + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + dci_length = sizeof_DCI1_20MHz_FDD_t; + dci_length_bytes = sizeof(DCI1_20MHz_FDD_t); + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + } + } + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes); + dci_alloc[num_dci].dci_length = dci_length; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = n_rnti+k; + dci_alloc[num_dci].format = format1; + + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + + + printf("Generating dlsch params for user %d\n",k); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + n_rnti+k, + format1, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[0].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + num_dci++; + num_ue_spec_dci++; + } + else { //common flag =1 + if (eNB->frame_parms.frame_type == TDD) { + + switch (eNB->frame_parms.N_RB_DL) { + + case 6: + dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); + break; + } + } + else { // fdd + switch (eNB->frame_parms.N_RB_DL) { + case 6: + dci_length = sizeof_DCI1A_1_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1A_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1A_10MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + dci_length = sizeof_DCI1A_20MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + } + } + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes); + dci_alloc[num_dci].dci_length = dci_length; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = SI_RNTI; + dci_alloc[num_dci].format = format1A; + dci_alloc[num_dci].firstCCE = 0; + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + printf("Generating dlsch params for user %d\n",k); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + SI_RNTI, + format1A, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[0].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + + num_common_dci++; + num_dci++; + + } + break; + case 3: //LARGE CDD + if (common_flag == 0) { + + if (eNB->frame_parms.nb_antennas_tx == 2) { + + if (eNB->frame_parms.frame_type == TDD) { + + switch (eNB->frame_parms.N_RB_DL) { + case 6: + dci_length = sizeof_DCI2A_1_5MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t); + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + case 25: + dci_length = sizeof_DCI2A_5MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2A_5MHz_2A_TDD_t); + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + case 50: + dci_length = sizeof_DCI2A_10MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2A_10MHz_2A_TDD_t); + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + case 100: + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + dci_length = sizeof_DCI2A_20MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2A_20MHz_2A_TDD_t); + break; + } + } + + else { // fdd + switch (eNB->frame_parms.N_RB_DL) { + case 6: + dci_length = sizeof_DCI2A_1_5MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t); + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + case 25: + dci_length = sizeof_DCI2A_5MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2A_5MHz_2A_FDD_t); + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + case 50: + dci_length = sizeof_DCI2A_10MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2A_10MHz_2A_FDD_t); + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + case 100: + dci_length = sizeof_DCI2A_20MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2A_20MHz_2A_FDD_t); + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + break; + } + } + } + else if (eNB->frame_parms.nb_antennas_tx == 4) { //4 antenna, needs diff precoding codebook index depeneding on layers + + + } + + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes); + dci_alloc[num_dci].dci_length = dci_length; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = n_rnti+k; + dci_alloc[num_dci].format = format2A; + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + + + printf("Generating dlsch params for user %d / format 2A (%d)\n",k,format2A); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + n_rnti+k, + format2A, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[0].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + + num_dci++; + num_ue_spec_dci++; + } + else { //commonn flag 1 + if (eNB->frame_parms.frame_type == TDD) { //tdd + + switch (eNB->frame_parms.N_RB_DL) { + + case 6: + dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); + break; + } + } + else { //fdd + switch (eNB->frame_parms.N_RB_DL) { + case 6: + dci_length = sizeof_DCI1A_1_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1A_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1A_10MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + dci_length = sizeof_DCI1A_20MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + } + } + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes); + dci_alloc[num_dci].dci_length = dci_length; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = SI_RNTI; + dci_alloc[num_dci].format = format1A; + dci_alloc[num_dci].firstCCE = 0; + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + + printf("Generating dlsch params for user %d\n",k); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + SI_RNTI, + format1A, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[0].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + + num_common_dci++; + num_dci++; + + } + printf("Generated DCI format 2A (Transmission Mode 3)\n"); + break; + + case 4: // !!! this dci format contains precoder information + if (common_flag == 0) { + + if (eNB->frame_parms.nb_antennas_tx == 2) { + + if (eNB->frame_parms.frame_type == TDD) { + + switch (eNB->frame_parms.N_RB_DL) { + + case 6: + dci_length = sizeof_DCI2_1_5MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t); + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + break; + case 25: + dci_length = sizeof_DCI2_5MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2_5MHz_2A_TDD_t); + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + + break; + case 50: + dci_length = sizeof_DCI2_10MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2_10MHz_2A_TDD_t); + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + + break; + case 100: + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + dci_length = sizeof_DCI2_20MHz_2A_TDD_t; + dci_length_bytes = sizeof(DCI2_20MHz_2A_TDD_t); + break; + } + } + + else { + + switch (eNB->frame_parms.N_RB_DL) { + + case 6: + dci_length = sizeof_DCI2_1_5MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t); + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + break; + case 25: + dci_length = sizeof_DCI2_5MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2_5MHz_2A_FDD_t); + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + break; + case 50: + dci_length = sizeof_DCI2_10MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2_10MHz_2A_FDD_t); + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + break; + case 100: + dci_length = sizeof_DCI2_20MHz_2A_FDD_t; + dci_length_bytes = sizeof(DCI2_20MHz_2A_FDD_t); + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tb_swap = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi = 2; + break; + } + } + } + else if (eNB->frame_parms.nb_antennas_tx == 4) { + + + } + + printf ("TM4 with tpmi =%d\n", ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi); + if ((((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 2) || (((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 2)) { + + eNB->UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff); + + + } + + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes); + dci_alloc[num_dci].dci_length = dci_length; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = n_rnti+k; + dci_alloc[num_dci].format = format2; + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + + + printf("Generating dlsch params for user %d\n",k); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + n_rnti+k, + format2, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[0].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + + num_dci++; + num_ue_spec_dci++; + } + else { //common_flag==1 + if (eNB->frame_parms.frame_type == TDD) { + + switch (eNB->frame_parms.N_RB_DL) { + case 6: + dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t; + dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); + break; + } + } + else { + + switch (eNB->frame_parms.N_RB_DL) { + case 6: + dci_length = sizeof_DCI1A_1_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 25: + dci_length = sizeof_DCI1A_5MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 50: + dci_length = sizeof_DCI1A_10MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + case 100: + dci_length = sizeof_DCI1A_20MHz_FDD_t; + dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1; + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0; + break; + } + } + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes); + dci_alloc[num_dci].dci_length = dci_length; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = SI_RNTI; + dci_alloc[num_dci].format = format1A; + dci_alloc[num_dci].firstCCE = 0; + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + + printf("Generating dlsch params for user %d\n",k); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + SI_RNTI, + format1A, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[0].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + + num_common_dci++; + num_dci++; + + } + break; + + case 5: + case 6: + memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu2_1E[k],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); + dci_alloc[num_dci].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t; + dci_alloc[num_dci].L = 1; + dci_alloc[num_dci].rnti = n_rnti+k; + dci_alloc[num_dci].format = format1E_2A_M10PRB; + dci_alloc[num_dci].firstCCE = 4*k; + printf("Generating dlsch params for user %d\n",k); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu2_1E[k], + n_rnti+k, + format1E_2A_M10PRB, + eNB->dlsch[k], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->UE_stats[k].DL_pmi_single, + transmission_mode>=7?transmission_mode:0); + + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); + num_ue_spec_dci++; + num_dci++; + + break; + + default: + printf("Unsupported Transmission Mode!!!"); + exit(-1); + break; + } + + + + + /* + memcpy(&dci_alloc[1].dci_pdu[0],&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD0_t)); + dci_alloc[1].dci_length = sizeof_DCI0_5MHz_TDD_0_t; + dci_alloc[1].L = 2; + dci_alloc[1].rnti = n_rnti; + */ + } + + if (n_frames==1) + printf("num_pdcch_symbols %d, numCCE %d => ",num_pdcch_symbols,numCCE); + + numCCE = get_nCCE(num_pdcch_symbols,&eNB->frame_parms,get_mi(&eNB->frame_parms,subframe)); + + + if (n_frames==1) + printf("%d\n",numCCE); + + // apply RNTI-based nCCE allocation + memset(CCE_table,0,800*sizeof(int)); + + for (i=num_common_dci; i<num_dci; i++) { + + dci_alloc[i].firstCCE = get_nCCE_offset_l1(CCE_table, + 1<<dci_alloc[i].L, + numCCE, + (dci_alloc[i].rnti==SI_RNTI)? 1 : 0, + dci_alloc[i].rnti, + subframe); + + if (n_frames==1) + printf("dci %d: rnti %x, format %d : nCCE %d/%d\n",i,dci_alloc[i].rnti, dci_alloc[i].format, + dci_alloc[i].firstCCE,numCCE); + } + + for (k=0; k<n_users; k++) { + + input_buffer_length0 = eNB->dlsch[k][0]->harq_processes[0]->TBS/8; + input_buffer0[k] = (unsigned char *)malloc(input_buffer_length0+4); + memset(input_buffer0[k],0,input_buffer_length0+4); + input_buffer_length1 = eNB->dlsch[k][1]->harq_processes[0]->TBS/8; + input_buffer1[k] = (unsigned char *)malloc(input_buffer_length1+4); + memset(input_buffer1[k],0,input_buffer_length1+4); + + if (input_trch_file==0) { + for (i=0; i<input_buffer_length0; i++) { + //input_buffer0[k][i] = (unsigned char)(i&0xff); + input_buffer0[k][i] = (unsigned char)(taus()&0xff); + } + + for (i=0; i<input_buffer_length1; i++) { + input_buffer1[k][i]= (unsigned char)(taus()&0xff); + } + } + + else { + i=0; + + while ((!feof(input_trch_fd)) && (i<input_buffer_length0<<3)) { + ret[0]=fscanf(input_trch_fd,"%s",input_trch_val); + + if (input_trch_val[0] == '1') + input_buffer0[k][i>>3]+=(1<<(7-(i&7))); + + if (i<16) + printf("input_trch_val %d : %c\n",i,input_trch_val[0]); + + i++; + + if (((i%8) == 0) && (i<17)) + printf("%x\n",input_buffer0[k][(i-1)>>3]); + } + + printf("Read in %d bits\n",i); + } + } + } + + snr_step = input_snr_step; + UE->high_speed_flag = 1; + UE->ch_est_alpha=0; + + for (ch_realization=0; ch_realization<n_ch_rlz; ch_realization++) { + if(abstx) { + printf("**********************Channel Realization Index = %d **************************\n", ch_realization); + } + + for (SNR=snr0; SNR<snr1; SNR+=snr_step) { + + UE->proc.proc_rxtx[0].frame_rx=0; + for (i=0; i<4; i++) { + errs[0][i]=0; //CW_0 + errs[1][i]=0; //CW_1 + decoded_in_sic[i]=0; + sic_attempt[i]=0; + resend_one[i]=0; + resend_both[i]=0; + + round_trials[0][i] = 0; // CW_0 + round_trials[1][i] = 0; // CW_1 + TB0_deact[i]=0; + TB1_deact[i]=0; + } + dci_errors=0; + + round = 0; + + avg_iter[0] = 0; + avg_iter[1] = 0; + iter_trials[0]=0; + iter_trials[1]=0; + + reset_meas(&eNB->phy_proc_tx); // total eNB tx + reset_meas(&eNB->dlsch_scrambling_stats); + reset_meas(&UE->dlsch_unscrambling_stats); + reset_meas(&eNB->ofdm_mod_stats); + reset_meas(&eNB->dlsch_modulation_stats); + reset_meas(&eNB->dlsch_encoding_stats); + reset_meas(&eNB->dlsch_interleaving_stats); + reset_meas(&eNB->dlsch_rate_matching_stats); + reset_meas(&eNB->dlsch_turbo_encoding_stats); + + reset_meas(&UE->phy_proc_rx[subframe&0x1]); // total UE rx + reset_meas(&UE->ofdm_demod_stats); + reset_meas(&UE->dlsch_channel_estimation_stats); + reset_meas(&UE->dlsch_freq_offset_estimation_stats); + reset_meas(&UE->rx_dft_stats); + reset_meas(&UE->dlsch_llr_stats); + reset_meas(&UE->dlsch_decoding_stats[0]); + reset_meas(&UE->dlsch_decoding_stats[1]); + reset_meas(&UE->dlsch_turbo_decoding_stats); + reset_meas(&UE->dlsch_deinterleaving_stats); + reset_meas(&UE->dlsch_rate_unmatching_stats); + reset_meas(&UE->dlsch_tc_init_stats); + reset_meas(&UE->dlsch_tc_alpha_stats); + reset_meas(&UE->dlsch_tc_beta_stats); + reset_meas(&UE->dlsch_tc_gamma_stats); + reset_meas(&UE->dlsch_tc_ext_stats); + reset_meas(&UE->dlsch_tc_intl1_stats); + reset_meas(&UE->dlsch_tc_intl2_stats); + + // initialization + struct list time_vector_tx; + initialize(&time_vector_tx); + struct list time_vector_tx_ifft; + initialize(&time_vector_tx_ifft); + struct list time_vector_tx_mod; + initialize(&time_vector_tx_mod); + struct list time_vector_tx_enc; + initialize(&time_vector_tx_enc); + + struct list time_vector_rx; + initialize(&time_vector_rx); + struct list time_vector_rx_fft; + initialize(&time_vector_rx_fft); + struct list time_vector_rx_demod; + initialize(&time_vector_rx_demod); + struct list time_vector_rx_dec; + initialize(&time_vector_rx_dec); + + for (trials = 0;trials<n_frames;trials++) { + //printf("Trial %d\n",trials); + fflush(stdout); + + round = 0; + is_first_time = true; +#ifdef DEBUG_HARQ + printf("[DLSIM] TRIAL %d\n", trials); + printf("TPMI_retr= %d\n", tpmi_retr); +#endif + + for (i=0; i<frame_parms->nb_antennas_tx; i++) { + memset(sic_buffer[i], 0, FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + } + + eNB2UE[0]->first_run = 1; + + ret[0] = UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations+1; + ret[1] = UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations+1; + + resend_cw0_cw1=1; + resend_cw1=0; + TB0_active=1; + TB1_active=1; + + while (((transmission_mode == 3 || transmission_mode == 4) && + ((round < num_rounds) && ((ret[0] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations) || + (ret[1] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations)))) || + ((transmission_mode!=4 && transmission_mode != 3) && ((round< num_rounds) && + (ret[0] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations)))) { +#ifdef DEBUG_HARQ + printf("\n [DLSIM] On top round is %d\n", round); +#endif + + + round_trials[0][round]++; + round_trials[1][round]++; + + //printf("Trial %d, round %d , ret[0] %d, ret[1] %d, round_trials %d\n",trials,round, ret[0], ret[1], round_trials[round]); + + /*if (ret[0] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations) { + round_trials[0][round]++; + round_trials[1][round]++; + } else if ((ret[1] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations) && (ret[0] <= UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations)) + round_trials[1][round]++;*/ + + +#ifdef DEBUG_HARQ + printf("[DLSIM] Just after while loop TB0 status %d TB1 status %d round %d\n", TB0_active, TB1_active, round); +#endif + + // printf("Trial %d, round %d , ret[0] %d, ret[1] %d, round_trials TB0 = %d, round_trials TB1 = %d \n",trials,round, ret[0], ret[1], round_trials[0][round], round_trials[1][round]); + + + /*printf("Trial %d, round cw0 = %d , round cw1 = %d, ret[0] = %d, ret[1] = %d, round_trials cw0 [%d]= %d, round_trials cw1 [%d]= %d\n",trials, round, round, \ + ret[0], ret[1], round, round_trials[0][round], round, round_trials[1][round]);*/ + + //printf("round_trials %d round %d\n", round_trials[round], round); + + if (transmission_mode == 4 || transmission_mode == 5 || transmission_mode == 6) + pmi_feedback=1; + else + pmi_feedback=0; + + if (abstx) { + if (trials==0 && round==0 && SNR==snr0) //generate a new channel + hold_channel = 0; + else + hold_channel = 1; + } + else + hold_channel = 0;//(round==0) ? 0 : 1; + + PMI_FEEDBACK: + + //printf("Trial %d : Round %d, pmi_feedback %d \n",trials,round,pmi_feedback); + for (aa=0; aa<eNB->frame_parms.nb_antennas_tx;aa++) { + memset(&eNB->common_vars.txdataF[eNB_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + } + + if (input_fd==NULL) { + + start_meas(&eNB->phy_proc_tx); + + // Simulate HARQ procedures!!! + if (common_flag == 0) { + + eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3; + if (transmission_mode == 3 || transmission_mode == 4) + eNB->dlsch[0][1]->harq_processes[0]->rvidx = round&3; + + if (round == 0) { // First round + TB0_active = 1; + TB1_active = 1; + + if (eNB->frame_parms.frame_type == TDD) { + + switch (transmission_mode) { + case 1: + case 2: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_TDD_t)); + break; + case 25: + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_TDD_t)); + break; + case 50: + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_TDD_t)); + break; + case 100: + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_TDD_t)); + break; + } + break; + case 3: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_TDD_t)); + break; + case 25: + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_TDD_t)); + break; + case 50: + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_TDD_t)); + break; + case 100: + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_TDD_t)); + break; + } + break; + case 4: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_1_5MHz_2A_TDD_t)); + break; + case 25: + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_5MHz_2A_TDD_t)); + break; + case 50: + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_10MHz_2A_TDD_t)); + break; + case 100: + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_20MHz_2A_TDD_t)); + break; + } + break; + case 5: + case 6: + DLSCH_alloc_pdu2_1E[0].ndi = trials&1; + DLSCH_alloc_pdu2_1E[0].rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); + break; + } + } + else { // FDD + switch (transmission_mode) { + case 1: + case 2: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_FDD_t)); + break; + case 25: + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_FDD_t)); + break; + case 50: + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_FDD_t)); + break; + case 100: + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_FDD_t)); + break; + } + break; + case 3: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_FDD_t)); + break; + case 25: + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_FDD_t)); + break; + case 50: + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_FDD_t)); + break; + case 100: + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_FDD_t)); + break; + } + break; + case 4: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_1_5MHz_2A_FDD_t)); + break; + case 25: + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_5MHz_2A_FDD_t)); + break; + case 50: + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_10MHz_2A_FDD_t)); + break; + case 100: + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_20MHz_2A_FDD_t)); + break; + } + break; + case 5: + case 6: + DLSCH_alloc_pdu2_1E[0].ndi = trials&1; + DLSCH_alloc_pdu2_1E[0].rv = 0; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); + break; + } + } + } + else { + + if (eNB->frame_parms.frame_type == TDD) { + switch (transmission_mode) { + case 1: + case 2: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_TDD_t)); + break; + case 25: + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_TDD_t)); + break; + case 50: + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_TDD_t)); + break; + case 100: + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_TDD_t)); + break; + } + break; + case 3: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0) { // deactivate TB0 + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_TDD_t)); + break; + case 25: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0) { // deactivate TB0 + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_TDD_t)); + break; + case 50: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_TDD_t)); + break; + case 100: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_TDD_t)); + break; + } + break; + case 4: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_1_5MHz_2A_TDD_t)); + break; + case 25: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 +#ifdef DEBUG_HARQ + printf("\n[DLSIM] Requesting only TB1 from temp DCI\n"); +#endif + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 +#ifdef DEBUG_HARQ + printf("\n[DLSIM] TDD Requesting only TB0 from temp DCI\n"); +#endif + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_5MHz_2A_TDD_t)); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + n_rnti+k, + format2, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + UE->dlsch[subframe&0x1][0][1]->pmi_alloc, + transmission_mode>=7?transmission_mode:0 + ); + break; + case 50: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_10MHz_2A_TDD_t)); + break; + case 100: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_20MHz_2A_TDD_t)); + break; + } + break; + + case 5: + case 6: + DLSCH_alloc_pdu2_1E[0].ndi = trials&1; + DLSCH_alloc_pdu2_1E[0].rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); + break; + } + } + else { + switch (transmission_mode) { + case 1: + case 2: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_FDD_t)); + break; + case 25: + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_FDD_t)); + break; + case 50: + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_FDD_t)); + break; + case 100: + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; + ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_FDD_t)); + break; + } + break; + case 3: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + if (TB0_active==1) { + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB0 + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_FDD_t)); + break; + case 25: + if (TB0_active==1) { + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB0 + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_FDD_t)); + break; + case 50: + if (TB0_active==1) { + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB0 + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_FDD_t)); + break; + case 100: + if (TB0_active==1) { + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB0 + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_FDD_t)); + break; + } + break; + case 4: + switch (eNB->frame_parms.N_RB_DL) { + case 6: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_1_5MHz_2A_FDD_t)); + break; + case 25: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 +#ifdef DEBUG_HARQ + printf("\n [DLSIM] Requesting only TB1 from temp DCI\n"); +#endif + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 +#ifdef DEBUG_HARQ + printf("\n[DLSIM] FDD Requesting only TB0 from temp DCI\n"); +#endif + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_5MHz_2A_FDD_t)); + generate_eNB_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + n_rnti+k, + format2, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + UE->dlsch[subframe&0x1][0][1]->pmi_alloc, + transmission_mode>=7?transmission_mode:0 + ); + break; + case 50: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0) { // deactivate TB0 + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_10MHz_2A_FDD_t)); + break; + case 100: + if (TB0_active == 1 && TB1_active == 1) { + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = mcs1; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = mcs2; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = 2; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else if (TB0_active == 0){ // deactivate TB0 + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3; + } + else { // deactivate TB1 + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->tpmi = tpmi_retr; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3; + ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs2 = 0; + ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 1; + } + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2_20MHz_2A_FDD_t)); + break; + } + break; + + + case 5: + case 6: + DLSCH_alloc_pdu2_1E[0].ndi = trials&1; + DLSCH_alloc_pdu2_1E[0].rv = round&3; + memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); + break; + } + } + } + } + num_pdcch_symbols_2 = generate_dci_top(num_ue_spec_dci, + num_common_dci, + dci_alloc, + 0, + AMP, + &eNB->frame_parms, + eNB->common_vars.txdataF[eNB_id], + subframe); + + if (num_pdcch_symbols_2 > num_pdcch_symbols) { + msg("Error: given num_pdcch_symbols not big enough (%d > %d)\n",num_pdcch_symbols_2,num_pdcch_symbols); + exit(-1); + } + + for (k=0;k<n_users;k++) { + for (int TB=0; TB<Kmimo; TB++) { + if (TB0_active == 0){ +#ifdef DEBUG_HARQ + printf("[DLSIM ENC] Skip TB0 \n"); +#endif + TB++; + } +#ifdef DEBUG_HARQ + printf("[DLSIM ENC] process TB %d \n", TB); +#endif + + if (TB==1 && TB1_active == 0){ +#ifdef DEBUG_HARQ + printf("[DLSIM ENC] Skip TB1 \n"); +#endif + break; + } + + coded_bits_per_codeword[TB] = get_G(&eNB->frame_parms, + eNB->dlsch[k][TB]->harq_processes[0]->nb_rb, + eNB->dlsch[k][TB]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[k][TB]->harq_processes[0]->mcs), + eNB->dlsch[k][TB]->harq_processes[0]->Nl, + num_pdcch_symbols, + 0,subframe, + transmission_mode>=7?transmission_mode:0); + #ifdef TBS_FIX // This is for MESH operation!!! + tbs[TB] = (double)3*TBStable[get_I_TBS(eNB->dlsch[k][TB]->harq_processes[0]->mcs)][eNB->dlsch[k][TB]->nb_rb-1]/4; + #else + tbs[TB] = eNB->dlsch[k][TB]->harq_processes[0]->TBS; + #endif + + rate[TB] = (double)tbs[TB]/(double)coded_bits_per_codeword[TB]; + + if ((SNR == snr0) && (trials == 0) && (round == 0) && (pmi_feedback == 0)) + printf("User %d, TB %d: Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n", + k,TB,rate[TB],rate[TB]*get_Qm(eNB->dlsch[k][TB]->harq_processes[0]->mcs), + coded_bits_per_codeword[TB], + tbs[TB], + get_Qm(eNB->dlsch[k][TB]->harq_processes[0]->mcs), + num_pdcch_symbols, + eNB->dlsch[k][TB]->harq_processes[0]->round); + + // use the PMI from previous trial + if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { + eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); + UE->dlsch[subframe&0x1][0][0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); + if (n_users>1) + eNB->dlsch[1][0]->harq_processes[0]->pmi_alloc = (eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555); + /* + if ((trials<10) && (round==0)) { + printf("tx PMI UE0 %x (pmi_feedback %d)\n",pmi2hex_2Ar1(eNB->dlsch[0][0]->pmi_alloc),pmi_feedback); + if (transmission_mode ==5) + printf("tx PMI UE1 %x\n",pmi2hex_2Ar1(eNB->dlsch[1][0]->pmi_alloc)); + } + */ + } + + //if standard case when both TBs are active + if (transmission_mode == 4) { + if (((((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 2) ||(((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 2)) && TB0_active == 1 && TB1_active == 1){ +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am calling from the eNode B 1\n"); +#endif + + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am calling from the eNode B 2\n"); +#endif + + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); + } + + else if (updated_csi == 0){ + + if (hold_rank1_precoder == 0 && ((((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 5) ||(((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 5))){ +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am calling from the eNode B 1\n"); +#endif + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = pmi_convert_rank1_from_rank2(eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc,5,eNB->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am calling from the eNode B 2\n"); +#endif + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = pmi_convert_rank1_from_rank2(UE->dlsch[subframe&0x1][0][TB]->pmi_alloc,5,UE->frame_parms.N_RB_DL); + } + + else if (hold_rank1_precoder == 0 && ((((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 6) ||(((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 6))){ +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am calling from the eNode B 1\n"); +#endif + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = pmi_convert_rank1_from_rank2(eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc,6,eNB->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am calling from the eNode B 2\n"); +#endif + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = pmi_convert_rank1_from_rank2(UE->dlsch[subframe&0x1][0][TB]->pmi_alloc,6,UE->frame_parms.N_RB_DL); + } + } else if (updated_csi == 1){ + + if (((((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 5) ||(((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 5))){ +#ifdef DEBUG_HARQ + printf ("[DLSIM] Updating CSI\n"); + printf ("[DLSIM] I quantize from ENodeB 1\n"); +#endif + + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I convert pmi to rank1 eNode B 1\n"); +#endif + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = pmi_convert_rank1_from_rank2(eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc,5,eNB->frame_parms.N_RB_DL); + +#ifdef DEBUG_HARQ + printf ("[DLSIM] I quantize from ENodeB 2\n"); +#endif + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I convert pmi to rank1 eNode B 2\n"); +#endif + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = pmi_convert_rank1_from_rank2(UE->dlsch[subframe&0x1][0][TB]->pmi_alloc,5,UE->frame_parms.N_RB_DL); + } + else if (((((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 6) ||(((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->tpmi == 6))){ +#ifdef DEBUG_HARQ + printf ("[DLSIM] Updating CSI\n"); + printf ("[DLSIM] I quantize from ENodeB 1\n"); +#endif + + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I convert pmi to rank1 eNode B 1\n"); +#endif + eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc = pmi_convert_rank1_from_rank2(eNB->dlsch[0][TB]->harq_processes[0]->pmi_alloc,6,eNB->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I quantize from ENodeB 2\n"); +#endif + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I convert pmi to rank1 eNode B 2\n"); +#endif + UE->dlsch[subframe&0x1][0][TB]->pmi_alloc = pmi_convert_rank1_from_rank2(UE->dlsch[subframe&0x1][0][TB]->pmi_alloc,6,UE->frame_parms.N_RB_DL); + } + + } + } + + start_meas(&eNB->dlsch_encoding_stats); + if (dlsch_encoding(eNB, + (TB==0) ? input_buffer0[k] : input_buffer1[k], + num_pdcch_symbols, + eNB->dlsch[k][TB], + 0, + subframe, + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_interleaving_stats)<0) + exit(-1); + + stop_meas(&eNB->dlsch_encoding_stats); + + eNB->dlsch[k][TB]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI; + start_meas(&eNB->dlsch_scrambling_stats); + dlsch_scrambling(&eNB->frame_parms, + 0, + eNB->dlsch[k][TB], + coded_bits_per_codeword[TB], + TB, + subframe<<1); + stop_meas(&eNB->dlsch_scrambling_stats); + + if (n_frames==2) { + for (s=0;s<eNB->dlsch[k][TB]->harq_processes[0]->C;s++) { + if (s<eNB->dlsch[k][TB]->harq_processes[0]->Cminus) + Kr = eNB->dlsch[k][TB]->harq_processes[0]->Kminus; + else + Kr = eNB->dlsch[k][TB]->harq_processes[0]->Kplus; + Kr_bytes = Kr>>3; + } + } + } + + start_meas(&eNB->dlsch_modulation_stats); + re_allocated = dlsch_modulation(eNB, + eNB->common_vars.txdataF[eNB_id], + AMP, + subframe, + num_pdcch_symbols, + ((TB0_active == 1)? eNB->dlsch[k][0]: NULL), + ((TB1_active == 1)? eNB->dlsch[k][1]: NULL)); + stop_meas(&eNB->dlsch_modulation_stats); + } //n_users + + + if (((transmission_mode == 3) || (transmission_mode == 4)) && (SNR == snr0) && (trials == 0) && (round == 0)){ + rate0_init = rate[0]; + rate1_init = rate[1]; + tbs0_init=tbs[0]; + tbs1_init=tbs[1]; + mod_order0_init=get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs); + mod_order1_init=get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs); + mcs0_init=eNB->dlsch[0][0]->harq_processes[0]->mcs; + mcs1_init=eNB->dlsch[0][1]->harq_processes[0]->mcs; + } + + generate_pilots(eNB, + eNB->common_vars.txdataF[eNB_id], + AMP, + LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); + + start_meas(&eNB->ofdm_mod_stats); + + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], + eNB->common_vars.txdata[eNB_id], + (subframe*2), + &eNB->frame_parms); + + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], + eNB->common_vars.txdata[eNB_id], + (subframe*2)+1, + &eNB->frame_parms); + + stop_meas(&eNB->ofdm_mod_stats); + stop_meas(&eNB->phy_proc_tx); + + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], + eNB->common_vars.txdata[eNB_id], + (subframe*2)+2, + &eNB->frame_parms); + + if (n_frames==1) { + write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); + if (eNB->frame_parms.nb_antennas_tx>1) + write_output("txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); + } + + tx_lev = 0; + for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) { + tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa] + [subframe*eNB->frame_parms.samples_per_tti], + eNB->frame_parms.samples_per_tti); + } + tx_lev_dB = (unsigned int) dB_fixed(tx_lev); + + if (n_frames==1) { + write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); + if (eNB->frame_parms.nb_antennas_tx>1) + write_output("txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); + } + + tx_lev = 0; + for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) { + tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa] + [subframe*eNB->frame_parms.samples_per_tti], + eNB->frame_parms.samples_per_tti); + } + tx_lev_dB = (unsigned int) dB_fixed(tx_lev); + + if (n_frames==2) { + printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB); + write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe*eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti,1,1); + } + } + // printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,eNB->frame_parms.nb_antennas_tx,awgn_flag); + for (i=0;i<2*frame_parms->samples_per_tti;i++) { + for (aa=0;aa<eNB->frame_parms.nb_antennas_tx;aa++) { + if (awgn_flag == 0) { + s_re[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); + s_im[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + } + else { + if (transmission_mode==4) { + r_re[0][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][0]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)])+((double)(((short *)eNB->common_vars.txdata[eNB_id][1]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[0][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][0]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1])+((double)(((short *)eNB->common_vars.txdata[eNB_id][1]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + + r_re[1][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][0]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)])-((double)(((short *)eNB->common_vars.txdata[eNB_id][1]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[1][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][0]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1])-((double)(((short *)eNB->common_vars.txdata[eNB_id][1]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + //printf("r_re0 = %d\n",r_re[0][i]); + //printf("r_im0 = %d\n",r_im[0][i]); + //printf("r_re1 = %d\n",r_re[1][i]); + //printf("r_im1 = %d\n",r_im[1][i]); + + } + else { + for (aarx=0;aarx<UE->frame_parms.nb_antennas_rx;aarx++) { + if (aa==0) { + r_re[aarx][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[aarx][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + } + else { + r_re[aarx][i] += ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[aarx][i] += ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + } + } + } + } + } + } + + // Multipath channel + if (awgn_flag == 0) { + multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im, + 2*frame_parms->samples_per_tti,hold_channel); + // printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset); + if(abstx==1 && num_rounds>1) + if(round==0 && hold_channel==0){ + random_channel(eNB2UE[1],0); + random_channel(eNB2UE[2],0); + random_channel(eNB2UE[3],0); + } + if (UE->perfect_ce==1){ + freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); + // write_output("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8); + // write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL +1,1,8); + } + } + + // freq_channel(eNB2UE[0], NB_RB,12*NB_RB + 1); + if(abstx){ + if (trials==0 && round==0) { + // calculate freq domain representation to compute SINR + freq_channel(eNB2UE[0], NB_RB,2*NB_RB + 1); + // snr=pow(10.0,.1*SNR); + fprintf(csv_fd,"%f,",SNR); + + for (u=0;u<2*NB_RB;u++){ + for (aarx=0;aarx<eNB2UE[0]->nb_rx;aarx++) { + for (aatx=0;aatx<eNB2UE[0]->nb_tx;aatx++) { + channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x; + channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + + if(num_rounds>1){ + freq_channel(eNB2UE[1], NB_RB,2*NB_RB + 1); + + for (u=0;u<2*NB_RB;u++){ + for (aarx=0;aarx<eNB2UE[1]->nb_rx;aarx++) { + for (aatx=0;aatx<eNB2UE[1]->nb_tx;aatx++) { + channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x; + channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + freq_channel(eNB2UE[2], NB_RB,2*NB_RB + 1); + + for (u=0;u<2*NB_RB;u++){ + for (aarx=0;aarx<eNB2UE[2]->nb_rx;aarx++) { + for (aatx=0;aatx<eNB2UE[2]->nb_tx;aatx++) { + channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x; + channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + + freq_channel(eNB2UE[3], NB_RB,2*NB_RB + 1); + + for (u=0;u<2*NB_RB;u++){ + for (aarx=0;aarx<eNB2UE[3]->nb_rx;aarx++) { + for (aatx=0;aatx<eNB2UE[3]->nb_tx;aatx++) { + channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x; + channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + } + } + } + + //AWGN + // tx_lev is the average energy over the whole subframe + // but SNR should be better defined wrt the energy in the reference symbols + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(eNB->frame_parms.N_RB_DL*12)) - SNR; + sigma2 = pow(10,sigma2_dB/10); + if (n_frames==1) + printf("Sigma2 %f (sigma2_dB %f,%f,%f )\n",sigma2,sigma2_dB,10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)),get_pa_dB(eNB->pdsch_config_dedicated)); + + for (i=0; i<2*frame_parms->samples_per_tti; i++) { + for (aa=0;aa<eNB->frame_parms.nb_antennas_rx;aa++) { + //printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]); + ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] = + (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] = + (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + } + } + + // lte_sync_time_init(eNB->frame_parms,common_vars); + // lte_sync_time(common_vars->rxdata, eNB->frame_parms); + // lte_sync_time_free(); + + /* + // optional: read rx_frame from file + if ((rx_frame_file = fopen("rx_frame.dat","r")) == NULL) + { + printf("Cannot open rx_frame.m data file\n"); + exit(0); + } + + result = fread((void *)PHY_vars->rx_vars[0].RX_DMA_BUFFER,4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file); + printf("Read %d bytes\n",result); + result = fread((void *)PHY_vars->rx_vars[1].RX_DMA_BUFFER,4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file); + printf("Read %d bytes\n",result); + + fclose(rx_frame_file); + */ + + if (n_frames==1) { + printf("RX level in null symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); + printf("RX level in data symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); + printf("rx_level Null symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)))); + printf("rx_level data symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)))); + } + + if (eNB->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + pilot2 = 7; + pilot3 = 11; + } + else { // extended prefix + pilot1 = 3; + pilot2 = 6; + pilot3 = 9; + } + + start_meas(&UE->phy_proc_rx[subframe&0x1]); + // Inner receiver scheduling for 3 slots + for (Ns=(2*subframe);Ns<((2*subframe)+3);Ns++) { + for (l=0;l<pilot2;l++) { + if (n_frames==1) + printf("Ns %d, l %d, l2 %d\n",Ns, l, l+(Ns%2)*pilot2); + /* + This function implements the OFDM front end processor (FEP). + + Parameters: + frame_parms LTE DL Frame Parameters + ue_common_vars LTE UE Common Vars + l symbol within slot (0..6/7) + Ns Slot number (0..19) + sample_offset offset within rxdata (points to beginning of subframe) + no_prefix if 1 prefix is removed by HW + + */ + + start_meas(&UE->ofdm_demod_stats); + slot_fep(UE, + l, + Ns%20, + 0, + 0, + 0); + + stop_meas(&UE->ofdm_demod_stats); + + if (UE->perfect_ce==1) { + + if (awgn_flag==0) { + for(k=0; k<NUMBER_OF_eNB_MAX; k++) { + for(aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + for (i=0; i<frame_parms->N_RB_DL*12; i++) { + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[k][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]= + (int16_t)(eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP); + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]= + (int16_t)(eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP); + } + } + } + } + }else { + if (transmission_mode==4) { + for (i=0; i<frame_parms->N_RB_DL*12; i++) { + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][0])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][0])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0; + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][1])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][1])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0; + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][2])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][2])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0; + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][3])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=-(short)(AMP); + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][3])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0; + } + } else { + for(aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { + for (i=0; i<frame_parms->N_RB_DL*12; i++) { + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); + ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2; + } + } + } + } + } + } + + if ((Ns==((2*subframe))) && (l==0)) { + lte_ue_measurements(UE, + subframe*UE->frame_parms.samples_per_tti, + 1, + 0, + subframe); + //printf ("Trial %d, Measurements are done \n", trials); + /* + debug_msg("RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), avg rx power %d dB (%d lin), RX gain %d dB\n", + UE->measurements.rx_rssi_dBm[0] - ((UE->frame_parms.nb_antennas_rx==2) ? 3 : 0), + UE->measurements.wideband_cqi_dB[0][0], + UE->measurements.wideband_cqi_dB[0][1], + UE->measurements.wideband_cqi[0][0], + UE->measurements.wideband_cqi[0][1], + UE->measurements.rx_power_avg_dB[0], + UE->measurements.rx_power_avg[0], + UE->rx_total_gain_dB); + debug_msg("N0 %d dBm digital (%d, %d) dB, linear (%d, %d), avg noise power %d dB (%d lin)\n", + UE->measurements.n0_power_tot_dBm, + UE->measurements.n0_power_dB[0], + UE->measurements.n0_power_dB[1], + UE->measurements.n0_power[0], + UE->measurements.n0_power[1], + UE->measurements.n0_power_avg_dB, + UE->measurements.n0_power_avg); + debug_msg("Wideband CQI tot %d dB, wideband cqi avg %d dB\n", + UE->measurements.wideband_cqi_tot[0], + UE->measurements.wideband_cqi_avg[0]); + */ + + if (transmission_mode == 4 || transmission_mode == 5 || transmission_mode == 6) { + if (pmi_feedback == 1) { + pmi_feedback = 0; + hold_channel = 1; + + if (updated_csi==0) { + if (hold_rank1_precoder == 0) + hold_rank1_precoder = 1; + } + //printf ("trial %d pmi_feedback %d \n", trials, pmi_feedback); + //printf ("go to PMI feedback\n"); +#ifdef DEBUG_HARQ + printf ("[DLSIM] I am doing measurements and coming back to reencoding\n"); +#endif + goto PMI_FEEDBACK; + } + } + + } + + + if ((Ns==(2*subframe)) && (l==pilot1)) {// process symbols 0,1,2 + if (dci_flag == 1) { + UE->UE_mode[0] = PUSCH; + start_meas(&UE->dlsch_rx_pdcch_stats); + + rx_pdcch(UE, + trials, + subframe, + 0, + (UE->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + UE->high_speed_flag, + UE->is_secondary_ue); + + stop_meas(&UE->dlsch_rx_pdcch_stats); + // overwrite number of pdcch symbols + UE->pdcch_vars[subframe&0x1][0]->num_pdcch_symbols = num_pdcch_symbols; + + dci_cnt = dci_decoding_procedure(UE, + dci_alloc_rx,1, + eNB_id, + subframe); + printf("dci_cnt %d\n",dci_cnt); + + if (dci_cnt==0) { + dlsch_active = 0; + if (round==0) { + dci_errors++; + + round=5; // this is meant to stop the "while" loop if DCI is wrong; + errs[0][0]++; + + if (n_frames==2) + printf("DCI error trial %d errs[0][0] %d\n",trials,errs[0][0]); + } + } + + for (i=0;i<dci_cnt;i++) { + //printf("Generating dlsch parameters for RNTI %x\n",dci_alloc_rx[i].rnti); + + if (round == 0) { + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx=1; + } + if ((transmission_mode == 3 || transmission_mode ==4) && (round == 0)) { + UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->first_tx=1; + } + + if ((dci_alloc_rx[i].rnti == n_rnti) && + (generate_ue_dlsch_params_from_dci(0, + subframe, + dci_alloc_rx[i].dci_pdu, + dci_alloc_rx[i].rnti, + dci_alloc_rx[i].format, + UE->dlsch[subframe&0x1][0], + &UE->frame_parms, + UE->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + transmission_mode<7?0:transmission_mode, + UE->pdcch_vars[subframe&0x1][0]->crnti_is_temporary? UE->pdcch_vars[subframe&0x1][0]->crnti: 0)==0)) { + dump_dci(&UE->frame_parms,&dci_alloc_rx[i]); + coded_bits_per_codeword[0]= get_G(&eNB->frame_parms, + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->nb_rb, + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->rb_alloc_even, + get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->Nl, + UE->pdcch_vars[subframe&0x1][0]->num_pdcch_symbols, + 0, + subframe, + transmission_mode>=7?transmission_mode:0); + if (transmission_mode == 3 || transmission_mode == 4) { + coded_bits_per_codeword[1]= get_G(&eNB->frame_parms, + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->nb_rb, + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->rb_alloc_even, + get_Qm(UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->Nl, + UE->pdcch_vars[subframe&0x1][1]->num_pdcch_symbols, + 0, + subframe, + transmission_mode>=7?transmission_mode:0); + } + /* + rate = (double)dlsch_tbs25[get_I_TBS(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs)][UE->dlsch[subframe&0x1][0][0]->nb_rb-1]/(coded_bits_per_codeword); + rate*=get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs); + */ + printf("num_pdcch_symbols %d, G %d, TBS %d\n",UE->pdcch_vars[subframe&0x1][0]->num_pdcch_symbols,coded_bits_per_codeword [0],UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->TBS); + + dlsch_active = 1; // what does it indicates??? + } else { + dlsch_active = 0; + if (round==0) { + dci_errors++; + errs[0][0]++; + //round_trials[0]++; + round=5; + + if (n_frames==1) + printf("DCI misdetection trial %d\n",trials); + + } + // for (i=1;i<=round;i++) + // round_trials[i]--; + // round=5; + } + } + } else { //dci_flag == 0 + UE->pdcch_vars[subframe&0x1][0]->crnti = n_rnti; + UE->pdcch_vars[subframe&0x1][0]->num_pdcch_symbols = num_pdcch_symbols; + if (round == 0) { + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx=1; + UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->first_tx=1; + } + + switch (transmission_mode) { + case 1: + case 2: + generate_ue_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + (common_flag==0)? C_RNTI : SI_RNTI, + (common_flag==0)? format1 : format1A, + UE->dlsch[subframe&0x1][0], + &UE->frame_parms, + UE->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + transmission_mode<7?0:transmission_mode, + UE->pdcch_vars[subframe&0x1][0]->crnti_is_temporary? UE->pdcch_vars[subframe&0x1][0]->crnti: 0); + break; + case 3: + + //printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx); + + generate_ue_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + (common_flag==0)? C_RNTI : SI_RNTI, + (common_flag==0)? format2A : format1A, + UE->dlsch[subframe&0x1][0], + &UE->frame_parms, + UE->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + transmission_mode<7?0:transmission_mode, + UE->pdcch_vars[subframe&0x1][0]->crnti_is_temporary? UE->pdcch_vars[subframe&0x1][0]->crnti: 0); + //printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx); + break; + case 4: + generate_ue_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu_1[0], + (common_flag==0)? C_RNTI : SI_RNTI, + (common_flag==0)? format2 : format1A,//format1A only for a codeblock + UE->dlsch[subframe&0x1][0], + &UE->frame_parms, + UE->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + transmission_mode<7?0:transmission_mode, + UE->pdcch_vars[subframe&0x1][0]->crnti_is_temporary? UE->pdcch_vars[subframe&0x1][0]->crnti: 0); + + break; + case 5: + case 6: + generate_ue_dlsch_params_from_dci(0, + subframe, + &DLSCH_alloc_pdu2_1E[0], + C_RNTI, + format1E_2A_M10PRB, + UE->dlsch[subframe&0x1][0], + &UE->frame_parms, + UE->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + transmission_mode<7?0:transmission_mode, + UE->pdcch_vars[subframe&0x1][0]->crnti_is_temporary? UE->pdcch_vars[subframe&0x1][0]->crnti: 0); + break; + } + dlsch_active = 1; + } // if dci_flag == 1 + } + + if (dlsch_active == 1) { + if (TB0_active==1) + cur_harq_pid =UE->dlsch[subframe&0x1][0][0]->current_harq_pid; + else + cur_harq_pid =UE->dlsch[subframe&0x1][0][1]->current_harq_pid; + + if ((Ns==(1+(2*subframe))) && (l==0)) {// process PDSCH symbols 1,2,3,4,5,(6 Normal Prefix + /* if (transmission_mode == 5) { + if ((UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[cur_harq_pid]->dl_power_off==0) && + (openair_daq_vars.use_ia_receiver ==1)) { + rx_type = rx_IC_single_stream; + } else { + rx_type = rx_standard; + } + }*/ + + + start_meas(&UE->dlsch_llr_stats); + + for (m=UE->pdcch_vars[subframe&0x1][0]->num_pdcch_symbols; m<pilot2; m++) { + if (rx_pdsch(UE, + PDSCH, + eNB_id, + eNB_id_i, + 0, + subframe, + m, + (m==UE->pdcch_vars[subframe&0x1][0]->num_pdcch_symbols)?1:0, + rx_type, + i_mod, + UE->dlsch[subframe&0x1][0][0]->current_harq_pid)==-1){ + dlsch_active = 0; + break; + } + } + stop_meas(&UE->dlsch_llr_stats); + } + + if ((Ns==(1+(2*subframe))) && (l==pilot1)){// process symbols (6 Extended Prefix),7,8,9 + start_meas(&UE->dlsch_llr_stats); + for (m=pilot2;m<pilot3; m++) { + if (rx_pdsch(UE, + PDSCH, + eNB_id, + eNB_id_i, + 0, + subframe, + m, + 0, + rx_type, + i_mod, + cur_harq_pid)==-1){ + dlsch_active=0; + break; + } + } + stop_meas(&UE->dlsch_llr_stats); + } + + if ((Ns==(2+(2*subframe))) && (l==0)) { // process symbols 10,11,(12,13 Normal Prefix) do deinterleaving for TTI + start_meas(&UE->dlsch_llr_stats); + for (m=pilot3; m<UE->frame_parms.symbols_per_tti; m++) { + if (rx_pdsch(UE, + PDSCH, + eNB_id, + eNB_id_i, + 0, + subframe, + m, + 0, + rx_type, + i_mod, + cur_harq_pid)==-1) { + dlsch_active=0; + break; + } + } + stop_meas(&UE->dlsch_llr_stats); + } + } + } + } + + //saving PMI in case of Transmission Mode > 5 + + if(abstx){ + if (trials==0 && round==0 && transmission_mode>=4){ + for (iii=0; iii<NB_RB; iii++){ + //fprintf(csv_fd, "%d, %d", (UE->pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id_i]->pmi_ext[iii])); + fprintf(csv_fd,"%x,",(UE->pdsch_vars[subframe&0x1][eNB_id]->pmi_ext[iii])); + //printf("%x ",(UE->pdsch_vars[eNB_id]->pmi_ext[iii])); + } + } + } + + + for (TB=0; TB<Kmimo; TB++){ // may be we ll have to swap CW + + + if (TB0_active == 0){ +#ifdef DEBUG_HARQ + printf("[DLSIM] Skip TB0 \n"); +#endif + TB++; + + } +#ifdef DEBUG_HARQ + printf("[DLSIM] process TB %d \n", TB); +#endif + + if (TB==1 && TB1_active == 0){ +#ifdef DEBUG_HARQ + printf("[DLSIM] Skip TB1 \n"); +#endif + break; + } + + UE->dlsch[subframe&0x1][0][TB]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; + coded_bits_per_codeword[TB] = get_G(&eNB->frame_parms, + eNB->dlsch[0][TB]->harq_processes[0]->nb_rb, + eNB->dlsch[0][TB]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[0][TB]->harq_processes[0]->mcs), + eNB->dlsch[0][TB]->harq_processes[0]->Nl, + num_pdcch_symbols, + 0,subframe, + transmission_mode>=7?transmission_mode:0); + + UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->G = coded_bits_per_codeword[TB]; + UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->Qm = get_Qm(eNB->dlsch[0][TB]->harq_processes[0]->mcs); + + if (n_frames==2) { + printf("Kmimo=%d, TB=%d, G=%d, TBS=%d\n",Kmimo,TB,coded_bits_per_codeword[TB], + UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->TBS); + + // calculate uncoded BER + uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword[TB]); + + AssertFatal(uncoded_ber_bit, "uncoded_ber_bit==NULL"); + + sprintf(fname,"dlsch%d_rxF_r%d_cw%d_llr.m",eNB_id,round, TB); + sprintf(vname,"dl%d_r%d_cw%d_llr",eNB_id,round, TB); + write_output(fname,vname, UE->pdsch_vars[subframe&0x1][0]->llr[UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->codeword],coded_bits_per_codeword[TB],1,0); + sprintf(fname,"dlsch_cw%d_e.m", TB); + sprintf(vname,"dlschcw%d_e", TB); + write_output(fname, vname,eNB->dlsch[0][TB]->harq_processes[0]->e,coded_bits_per_codeword[TB],1,4); + uncoded_ber=0; + printf("trials=%d\n", trials); + + for (i=0;i<coded_bits_per_codeword[TB];i++) + if (eNB->dlsch[0][TB]->harq_processes[0]->e[i] != (UE->pdsch_vars[subframe&0x1][0]->llr[UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->codeword][i]<0)) { + uncoded_ber_bit[i] = 1; + uncoded_ber++; + } + else + uncoded_ber_bit[i] = 0; + + uncoded_ber/=coded_bits_per_codeword[TB]; + avg_ber += uncoded_ber; + sprintf(fname,"cw%d_uncoded_ber_bit.m", TB); + sprintf(vname,"uncoded_ber_bit_cw%d", TB); + write_output(fname, vname,uncoded_ber_bit,coded_bits_per_codeword[TB],1,0); + printf("cw %d, uncoded ber %f\n",TB,uncoded_ber); + + free(uncoded_ber_bit); + uncoded_ber_bit = NULL; + + } + + start_meas(&UE->dlsch_unscrambling_stats); + dlsch_unscrambling(&UE->frame_parms, + 0, + UE->dlsch[subframe&0x1][0][TB], + coded_bits_per_codeword[TB], + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->codeword], + TB, + subframe<<1); + stop_meas(&UE->dlsch_unscrambling_stats); + + start_meas(&UE->dlsch_decoding_stats[subframe&0x1]); + ret[TB] = dlsch_decoding(UE, + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid]->codeword], + &UE->frame_parms, + UE->dlsch[subframe&0x1][0][TB], + UE->dlsch[subframe&0x1][0][TB]->harq_processes[UE->dlsch[subframe&0x1][0][TB]->current_harq_pid], + 0, + subframe, + UE->dlsch[subframe&0x1][0][TB]->current_harq_pid, + 1,llr8_flag); + stop_meas(&UE->dlsch_decoding_stats[subframe&0x1]); +#ifdef DEBUG_HARQ + printf("[DLSIM] ret[%d] = %d\n", TB, ret[TB]); +#endif + + //printf("retr cw 0 = %d\n", ret[0]); + //printf("current round = %d\n", UE->dlsch[subframe&0x1][0][cw_non_sic]->harq_processes[UE->dlsch[subframe&0x1][0][cw_non_sic]->current_harq_pid]->round); + + + + if (ret[TB] <= UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations ) { //if CW0 is decoded, approach CW1 +#ifdef DEBUG_HARQ + printf("[DLSIM] TB%d is decoded\n", TB); +#endif + + /*avg_iter[TB] += ret[TB]; + iter_trials[TB]++;*/ + + if (n_frames==2) { + printf("cw non sic %d, round %d: No DLSCH errors found, uncoded ber %f\n",TB,round,uncoded_ber); +#ifdef PRINT_BYTES + for (s=0;s<UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->C;s++) { + if (s<UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->Cminus) + Kr = UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->Kminus; + else + Kr = UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->Kplus; + + Kr_bytes = Kr>>3; + + printf("Decoded_output (Segment %d):\n",s); + for (i=0;i<Kr_bytes;i++) + printf("%d : %x (%x)\n",i,UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->c[s][i], + UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->c[s][i]^eNB->dlsch[0][TB]->harq_processes[0]->c[s][i]); + } +#endif + } + + UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[subframe&0x1][eNB_id][TB]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][TB]->current_harq_pid]->TBS; + + // If the receiver is NOT SIC, Here we are done with both CW, now only to calculate BLER + //If the receiver IS SIC, we are done only with CW0, CW1 was only compensated by this moment (y1' obtained) + if (UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC + /* + //for (round = 0 ; round < UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->round ; round++) { + // we assume here that the second stream has a lower MCS and is thus more likely to be decoded + // re-encoding of second stream + dlsch0_ue_harq = UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]; + dlsch0_eNB_harq = UE->dlsch[subframe&0x1][eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]; + + dlsch0_eNB_harq->mimo_mode = LARGE_CDD; + dlsch0_eNB_harq->rb_alloc[0] = dlsch0_ue_harq->rb_alloc[0]; + dlsch0_eNB_harq->nb_rb = dlsch0_ue_harq->nb_rb; + dlsch0_eNB_harq->mcs = dlsch0_ue_harq->mcs; + dlsch0_eNB_harq->rvidx = dlsch0_ue_harq->rvidx; + dlsch0_eNB_harq->Nl = dlsch0_ue_harq->Nl; + dlsch0_eNB_harq->round = dlsch0_ue_harq->round; + + dlsch0_eNB_harq->TBS = dlsch0_ue_harq->TBS; + dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off; + dlsch0_eNB_harq->status = dlsch0_ue_harq->status; + + UE->dlsch[subframe&0x1][eNB_id]->active = UE->dlsch[subframe&0x1][eNB_id][0]->active; + UE->dlsch[subframe&0x1][eNB_id]->rnti = UE->dlsch[subframe&0x1][eNB_id][0]->rnti; + UE->dlsch[subframe&0x1][eNB_id]->current_harq_pid = UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid; + + dlsch_encoding(UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->b, + &UE->frame_parms, + num_pdcch_symbols, + UE->dlsch[subframe&0x1][eNB_id], + 0,subframe, + &UE->dlsch_rate_matching_stats, + &UE->dlsch_turbo_encoding_stats, + &UE->dlsch_interleaving_stats + ); + + coded_bits_per_codeword = get_G(&UE->frame_parms, + UE->dlsch[subframe&0x1][eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id]->current_harq_pid]->nb_rb, + UE->dlsch[subframe&0x1][eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id]->current_harq_pid]->rb_alloc, + get_Qm(UE->dlsch[subframe&0x1][eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id]->current_harq_pid]->mcs), + UE->dlsch[subframe&0x1][eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id]->current_harq_pid]->Nl, + num_pdcch_symbols, + 0,subframe); + + + //scrambling + dlsch_scrambling(&UE->frame_parms, + 0, + UE->dlsch[subframe&0x1][eNB_id], + coded_bits_per_codeword, + 0, + subframe<<1); + + + //modulation + re_allocated = dlsch_modulation(sic_buffer, + AMP, + subframe, + &UE->frame_parms, + num_pdcch_symbols, + &UE->dlsch[subframe&0x1][0][0], + NULL); + // sic_buffer is a vector of size nb_antennas_tx, but both contain the same signal, since we do modulation without precoding + // precoding is contained in effective channel estimate + // compute the norm of the effective channel for both receive antennas -> alphha[0], alphha[2] + // multiply with the norm of the effective channnel + */ + + //stripping (from matched filter output of first stream = rxdataF_comp0) + // this is pseudocode + /* + for (i=0; i<frame_parms->nb_antennas_rx; i++) { + UE->pdsch_vars[eNB_id].rxdataF_ext[i] -= alpha[i].*sic_buffer[i]; + } + */ + + //apply rho to output + /* + dlsch_channel_compensation(UE->pdsch_vars[eNB_id].rxdataF_ext, + UE->pdsch_vars[eNB_id].dl_ch_rho_ext[harq_pid][round], + UE->pdsch_vars[eNB_id]->dl_ch_mag1, + UE->pdsch_vars[eNB_id]->dl_ch_magb1, + UE->pdsch_vars[eNB_id]->rxdataF_comp1, + NULL, + frame_parms, + symbol, + first_symbol_flag, + i_mod, + nb_rb, + pdsch_vars[eNB_id]->log2_maxh, + phy_measurements); // log2_maxh+I0_shift + */ + + + //detection of second stream + //} + + } + + + if ((UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && + (UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode <=DUALSTREAM_PUSCH_PRECODING) && (TB0_active == 1) && + (rx_type==rx_SIC_dual_stream)) { +#ifdef DEBUG_HARQ + printf("[DLSIM] Starting SIC procedure\n"); +#endif + // printf("current round = %d\n", PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]->round); + + + //printf("\n CW 0 is decoded, i go for , round %d\n", round); + //printf("\n ret[TB0] = %d round %d\n", ret[TB], round); + sic_attempt[round]++; + + for (round_sic = 0 ; round_sic < (round +1); round_sic++) { + +#ifdef DEBUG_HARQ + printf("[DLSIM] 0 Round sic = %d\n", round_sic); +#endif + //printf("I enter round_sic loop \n"); + //printf("round_sic= %d\n", round_sic); + dlsch0_ue_harq = UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]; + dlsch0_eNB_harq = UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]; + + dlsch0_eNB_harq->mimo_mode = UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode; + dlsch0_eNB_harq->rb_alloc[0] = dlsch0_ue_harq->rb_alloc_even[0]; + dlsch0_eNB_harq->nb_rb = dlsch0_ue_harq->nb_rb; + dlsch0_eNB_harq->mcs = dlsch0_ue_harq->mcs; + dlsch0_eNB_harq->rvidx = dlsch0_ue_harq->rvidx; + dlsch0_eNB_harq->Nl = dlsch0_ue_harq->Nl; + dlsch0_eNB_harq->round = dlsch0_ue_harq->round; + dlsch0_eNB_harq->TBS = dlsch0_ue_harq->TBS; + dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off; + dlsch0_eNB_harq->status = dlsch0_ue_harq->status; + + if (round_sic == 0){ + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][1]->current_harq_pid]->rvidx = 0; + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->rvidx=0; + } + else if (round_sic == 1){ + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][1]->current_harq_pid]->rvidx = 1; + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->rvidx=1; + } + else if (round_sic == 2){ + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][1]->current_harq_pid]->rvidx = 2; + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->rvidx=2; + } + else{ + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][1]->current_harq_pid]->rvidx = 3; + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->rvidx=3; + } + + UE->dlsch_eNB[eNB_id]->active = UE->dlsch[subframe&0x1][eNB_id][0]->active; + UE->dlsch_eNB[eNB_id]->rnti = UE->dlsch[subframe&0x1][eNB_id][0]->rnti; + UE->dlsch_eNB[eNB_id]->current_harq_pid = UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid; + + dlsch_encoding_SIC(UE, + input_buffer0[0], //UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]->b,, + num_pdcch_symbols, + UE->dlsch_eNB[eNB_id], + 0, + subframe, + &UE->dlsch_rate_matching_stats, + &UE->dlsch_turbo_encoding_stats, + &UE->dlsch_interleaving_stats); + + + coded_bits_per_codeword[0]= get_G(&UE->frame_parms, + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch_eNB[eNB_id]->current_harq_pid]->nb_rb, + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch_eNB[eNB_id]->current_harq_pid]->rb_alloc, + get_Qm(UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch_eNB[eNB_id]->current_harq_pid]->mcs), + UE->dlsch_eNB[eNB_id]->harq_processes[UE->dlsch_eNB[eNB_id]->current_harq_pid]->Nl, + num_pdcch_symbols, + 0, + subframe, + transmission_mode>=7?transmission_mode:0); + + dlsch_scrambling(&UE->frame_parms, + 0, + UE->dlsch_eNB[eNB_id], + coded_bits_per_codeword[0], + 0, + subframe<<1); + + re_allocated = dlsch_modulation_SIC(sic_buffer, + subframe, + &UE->frame_parms, + num_pdcch_symbols, + &UE->dlsch_eNB[0][0], + coded_bits_per_codeword[0]); + + // write_output("sic_buffer.m","sic", *sic_buffer,re_allocated,1,1); + // write_output("rxdataF_comp1.m","rxF_comp1", *UE->pdsch_vars[eNB_id]->rxdataF_comp1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round],14*12*25,1,1); + // write_output("rxdataF_rho.m","rho", *UE->pdsch_vars[eNB_id]->dl_ch_rho_ext[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round],14*12*25,1,1); + + + switch (get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs)){ + + + + case 2: + + dlsch_qpsk_llr_SIC(&UE->frame_parms, + UE->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + sic_buffer, + UE->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_rho_ext[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword], + num_pdcch_symbols, + dlsch0_eNB_harq->nb_rb, + subframe, + dlsch0_eNB_harq->rb_alloc[0], + get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs), + UE->dlsch[subframe&0x1][eNB_id][0]); + break; + + case 4: + + dlsch_16qam_llr_SIC(&UE->frame_parms, + UE->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + sic_buffer, + UE->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_rho_ext[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword], + num_pdcch_symbols, + UE->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + dlsch0_eNB_harq->nb_rb, + subframe, + dlsch0_eNB_harq->rb_alloc[0], + get_Qm(eNB->dlsch[0][TB]->harq_processes[0]->mcs), + UE->dlsch[subframe&0x1][eNB_id][0]); + break; + case 6: + dlsch_64qam_llr_SIC(&UE->frame_parms, + UE->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + sic_buffer, + UE->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_rho_ext[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword], + num_pdcch_symbols, + UE->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + UE->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_magb1[UE->dlsch[subframe&0x1][0][0]->current_harq_pid][round_sic], + dlsch0_eNB_harq->nb_rb, + subframe, + dlsch0_eNB_harq->rb_alloc[0], + get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs), + UE->dlsch[subframe&0x1][eNB_id][TB]); + break; + } + //}// rouns sic +#ifdef DEBUG_HARQ + printf("[DLSIM] TB1 is mapped into CW%d\n", UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword); +#endif + + // write_output("rxdata_llr1.m","llr1", UE->pdsch_vars[eNB_id]->llr[1],re_allocated*2,1,0); + + // replace cw_sic with TB+1 + UE->dlsch[subframe&0x1][0][1]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; + coded_bits_per_codeword[1]= get_G(&eNB->frame_parms, + eNB->dlsch[0][1]->harq_processes[0]->nb_rb, + eNB->dlsch[0][1]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs), + eNB->dlsch[0][1]->harq_processes[0]->Nl, + num_pdcch_symbols, + 0, + subframe, + transmission_mode>=7?transmission_mode:0); + + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->G = coded_bits_per_codeword[1]; + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->Qm = get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs); + + if (n_frames==2) { + printf("Kmimo=%d, cw=%d, G=%d, TBS=%d\n",Kmimo,1,coded_bits_per_codeword[1], + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->TBS); + + // calculate uncoded BER + uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword[1]); + AssertFatal(uncoded_ber_bit, "uncoded_ber_bit==NULL"); + sprintf(fname,"dlsch%d_rxF_r%d_cw%d_llr.m",eNB_id,round,1); + sprintf(vname,"dl%d_r%d_cw%d_llr",eNB_id,round, 1); + write_output(fname,vname, UE->pdsch_vars[subframe&0x1][0]->llr[1],coded_bits_per_codeword[1],1,0); + sprintf(fname,"dlsch_cw%d_e.m", 1); + sprintf(vname,"dlschcw%d_e", 1); + write_output(fname, vname,eNB->dlsch[0][1]->harq_processes[0]->e,coded_bits_per_codeword[1],1,4); + uncoded_ber=0; + printf("trials=%d\n", trials); + for (i=0;i<coded_bits_per_codeword[1];i++) + if (eNB->dlsch[0][1]->harq_processes[0]->e[i] != (UE->pdsch_vars[subframe&0x1][0]->llr[UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword][i]<0)) { + uncoded_ber_bit[i] = 1; + uncoded_ber++; + } + else + uncoded_ber_bit[i] = 0; + + uncoded_ber/=coded_bits_per_codeword[1]; + avg_ber += uncoded_ber; + sprintf(fname,"cw%d_uncoded_ber_bit.m", 1); + sprintf(vname,"uncoded_ber_bit_cw%d", 1); + write_output(fname, vname,uncoded_ber_bit,coded_bits_per_codeword[1],1,0); + printf("cw %d, uncoded ber %f\n",1,uncoded_ber); + free(uncoded_ber_bit); + uncoded_ber_bit = NULL; + } + + start_meas(&UE->dlsch_unscrambling_stats); + dlsch_unscrambling(&UE->frame_parms, + 0, + UE->dlsch[subframe&0x1][0][1], + coded_bits_per_codeword[1], + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword], + 1, + subframe<<1); + stop_meas(&UE->dlsch_unscrambling_stats); + + start_meas(&UE->dlsch_decoding_stats[subframe&0x1]); + + ret[1] = dlsch_decoding(UE, + UE->pdsch_vars[subframe&0x1][eNB_id]->llr[UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid]->codeword], + &UE->frame_parms, + UE->dlsch[subframe&0x1][0][1], + UE->dlsch[subframe&0x1][0][1]->harq_processes[UE->dlsch[subframe&0x1][0][1]->current_harq_pid], + 0, + subframe, + UE->dlsch[subframe&0x1][0][1]->current_harq_pid, + 1,llr8_flag); + stop_meas(&UE->dlsch_decoding_stats[subframe&0x1]); + +#ifdef DEBUG_HARQ + printf("[DLSIM] Decoding TB1 in SIC: ret[1] = %d, round sic %d\n", ret[1], round_sic); +#endif + + //printf("ret TB 1 = %d round %d \n", ret[1], round); + + if (ret[1] <=UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations ) { + decoded_in_sic[round]++; + round_sic = round+1; // to exit round_sic +#ifdef DEBUG_HARQ + printf("[DLSIM] TB1 is decoded in SIC loop\n"); +#endif + avg_iter[1] += ret[1]; + iter_trials[1]++; + + + if (n_frames==2) { + printf("cw sic %d, round %d: No DLSCH errors found, uncoded ber %f\n",1,round,uncoded_ber); + + #ifdef PRINT_BYTES + for (s=0;s<UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->C;s++) { + if (s<UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->Cminus) + Kr = UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->Kminus; + else + Kr = UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->Kplus; + + Kr_bytes = Kr>>3; + + printf("Decoded_output (Segment %d):\n",s); + + for (i=0;i<Kr_bytes;i++) + printf("%d : %x (%x)\n",i,UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->c[s][i], + UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->c[s][i]^eNB->dlsch[0][1]->harq_processes[0]->c[s][i]); + } + #endif + } + } + } //round_sic + + + if (ret[1] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations ){ + errs[1][round]++; +#ifdef DEBUG_HARQ + printf("[DLSIM] TB1 is not decoded in SIC loop, errs[TB1][round %d] = %d\n",round, errs[1][round]); +#endif + + // exit(0); + + avg_iter[1] += ret[1]-1; + iter_trials[1]++; + + if (n_frames==2) { + //if ((n_frames==1) || (SNR>=30)) { + printf("cw sic %d, round %d: DLSCH errors found, uncoded ber %f\n",1,round,uncoded_ber); +#ifdef PRINT_BYTES + for (s=0;s<UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->C;s++) { + if (s<UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->Cminus) + Kr = UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->Kminus; + else + Kr = UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->Kplus; + + Kr_bytes = Kr>>3; + + printf("Decoded_output (Segment %d):\n",s); + for (i=0;i<Kr_bytes;i++) + printf("%d : %x (%x)\n",i,UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->c[s][i], + UE->dlsch[subframe&0x1][0][1]->harq_processes[0]->c[s][i]^eNB->dlsch[0][1]->harq_processes[0]->c[s][i]); + } +#endif + } //n_frames==1 + // exit(0); + } //if (ret > UE->dlsch[subframe&0x1][0][1]->max_turbo_iterations ) + }//if SIC + } else { + + errs[TB][round]++; +#ifdef DEBUG_HARQ + printf("[DLSIM] TB%d is not decoded outside SIC loop, errs[TB%d][round %d] = %d\n", TB, TB, round, errs[TB][round]); +#endif + + + /*if (cw_non_sic==0) { + avg_iter[0] += ret[0]-1; + iter_trials[0]++; + }*/ + + if ((UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && + (UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode <=DUALSTREAM_PUSCH_PRECODING) && + (rx_type==rx_SIC_dual_stream) && (TB0_active ==1)) { + errs[1][round]++; +#ifdef DEBUG_HARQ + printf("[DLSIM] TB%d is not decoded outside SIC loop, errs[TB%d][round %d] = %d\n", 1, 1, round, errs[1][round]); +#endif + } + + + /*if (cw_non_sic==1) { + avg_iter[1] += ret[1]-1; + iter_trials[1]++; + }*/ + + + if (n_frames==2) { + //if ((n_frames==1) || (SNR>=30)) { + printf("cw %d, round %d: DLSCH errors found, uncoded ber %f\n",TB,round,uncoded_ber); +#ifdef PRINT_BYTES + for (s=0;s<UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->C;s++) { + if (s<UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->Cminus) + Kr = UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->Kminus; + else + Kr = UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->Kplus; + + Kr_bytes = Kr>>3; + + printf("Decoded_output (Segment %d):\n",s); + for (i=0;i<Kr_bytes;i++) + printf("%d : %x (%x)\n",i,UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->c[s][i], + UE->dlsch[subframe&0x1][0][TB]->harq_processes[0]->c[s][i]^eNB->dlsch[0][TB]->harq_processes[0]->c[s][i]); + } +#endif + } + } + if (rx_type==rx_SIC_dual_stream) + TB++; // to terminate the loop over TB + } + + stop_meas(&UE->phy_proc_rx[subframe&0x1]); + + if (n_frames==1) { + + //rxsig + sprintf(fname,"rxsig0_r%d.m",round); + sprintf(vname,"rxs0_r%d",round); + write_output(fname,vname, &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); + sprintf(fname,"rxsigF0_r%d.m",round); + sprintf(vname,"rxs0F_r%d",round); + write_output(fname,vname, &UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0][0],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1); + if (UE->frame_parms.nb_antennas_rx>1) { + sprintf(fname,"rxsig1_r%d.m",round); + sprintf(vname,"rxs1_r%d",round); + write_output(fname,vname, UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); + sprintf(fname,"rxsig1F_r%d.m",round); + sprintf(vname,"rxs1F_r%d",round); + write_output(fname,vname, UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[1],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1); + } + + //channel + write_output("chanF11.m","chF11",eNB2UE[0]->chF[0],12*NB_RB,1,8); + write_output("chan11.m","ch11",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8); + + if (eNB->frame_parms.nb_antennas_rx==2 && eNB->frame_parms.nb_antennas_tx==1 ){ + write_output("chan21.m","ch21",eNB2UE[0]->ch[1],eNB2UE[0]->channel_length,1,8); + } + if (eNB->frame_parms.nb_antennas_tx>1){ + write_output("chan12.m","ch12",eNB2UE[0]->ch[1],eNB2UE[0]->channel_length,1,8); + if ( eNB->frame_parms.nb_antennas_rx>1){ + write_output("chan21.m","ch21",eNB2UE[0]->ch[2],eNB2UE[0]->channel_length,1,8); + write_output("chan22.m","ch22",eNB2UE[0]->ch[3],eNB2UE[0]->channel_length,1,8); + } + } + + //channel estimates + sprintf(fname,"dlsch00_r%d.m",round); + sprintf(vname,"dl00_r%d",round); + write_output(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][0][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + if (UE->frame_parms.nb_antennas_rx>1) { + sprintf(fname,"dlsch01_r%d.m",round); + sprintf(vname,"dl01_r%d",round); + write_output(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][1][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + } + if (eNB->frame_parms.nb_antennas_tx>1) { + sprintf(fname,"dlsch10_r%d.m",round); + sprintf(vname,"dl10_r%d",round); + write_output(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + } + if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) { + sprintf(fname,"dlsch11_r%d.m",round); + sprintf(vname,"dl11_r%d",round); + write_output(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][3][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + } + //pdsch_vars + dump_dlsch2(UE,eNB_id,subframe,coded_bits_per_codeword,round, UE->dlsch[subframe&0x1][0][0]->current_harq_pid); + /* + write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + write_output("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); + write_output("dlsch_eNB_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4); + write_output("dlsch_UE_w.m","w",UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); + */ + + //pdcch_vars + write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[subframe&0x1][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[subframe&0x1][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[subframe&0x1][eNB_id]->rxdataF_comp[0],4*300,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[subframe&0x1][eNB_id]->llr,2400,1,4); + + if (round == 3) exit(-1); + } + + if (xforms==1) { + phy_scope_UE(form_ue, + UE, + eNB_id, + 0,// UE_id + subframe); + } +#ifdef DEBUG_HARQ + printf("[DLSIM] Errors errs[TB0][round %d] = %d, errs[TB1][round %d] = %d\n ", round, errs[0][round], round, errs[1][round]); +#endif + + if ((transmission_mode != 3) && (transmission_mode !=4) && (ret[0] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations)){ + //printf("flag 1 \n"); + round++; + } + + + if (transmission_mode == 3 || transmission_mode == 4 ) { + if (ret[0] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations && + ret[1] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations){ + resend_both[round]++; + round++; + resend_cw0_cw1=1; //resend both cws + resend_cw1=0; + TB0_active=1; + TB1_active=1; + } + else if (ret[1] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations && + ret[0] <= UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations){ + resend_one[round]++; + resend_cw0_cw1=0; + TB0_active=0; + TB1_active=1; + if (rx_type == rx_IC_dual_stream) + TB0_deact[round]++; + if(is_first_time) { + hold_rank1_precoder = 0; + is_first_time = false; + } + else + hold_rank1_precoder = 1; + +#ifdef DEBUG_HARQ + printf("[DLSIM] ret[TB0] =%d, ret[TB1] =%d, trial %d \n", ret[0], ret[1], trials); + printf("[DLSIM] TB0 deactivated\n"); +#endif + round++; + } + else if (ret[0] > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations && + ret[1] <= UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations){ + resend_one[round]++; + resend_cw0_cw1=0; + TB0_active=1; + TB1_active=0; + if (rx_type == rx_IC_dual_stream) + TB1_deact[round]++; + if(is_first_time) { + hold_rank1_precoder = 0; + is_first_time = false; + } + else + hold_rank1_precoder = 1; + +#ifdef DEBUG_HARQ + printf("[DLSIM] ret[TB0] =%d, ret[TB1] =%d, trial %d \n", ret[0], ret[1], trials); + printf("[DLSIM] TB1 deactivated\n"); +#endif + round++; + } + } + +#ifdef DEBUG_HARQ + printf("[DLSIM] Now round is %d, trial %d\n" , round, trials); +#endif + } + + + if(transmission_mode != 3 && transmission_mode !=4 ){ + if ((errs[0][0]>=n_frames/10) && (trials>(n_frames/2)) ) + break; + } + + //len = chbch_stats_read(stats_buffer,NULL,0,4096); + //printf("%s\n\n",stats_buffer); + + if (UE->proc.proc_rxtx[0].frame_rx % 10 == 0) { + UE->bitrate[eNB_id] = (UE->total_TBS[eNB_id] - UE->total_TBS_last[eNB_id])*10; + LOG_D(PHY,"[UE %d] Calculating bitrate: total_TBS = %d, total_TBS_last = %d, bitrate = %d kbits/s\n",UE->Mod_id,UE->total_TBS[eNB_id],UE->total_TBS_last[eNB_id],UE->bitrate[eNB_id]/1000); + UE->total_TBS_last[eNB_id] = UE->total_TBS[eNB_id]; + } + + + UE->proc.proc_rxtx[0].frame_rx++; + + /* calculate the total processing time for each packet, + * get the max, min, and number of packets that exceed t>2000us + */ + double t_tx = (double)eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; + double t_tx_ifft = (double)eNB->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx_mod = (double)eNB->dlsch_modulation_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; + + + double t_rx = (double)UE->phy_proc_rx[subframe&0x1].p_time/cpu_freq_GHz/1000.0; + double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_dec = (double)UE->dlsch_decoding_stats[subframe&0x1].p_time/cpu_freq_GHz/1000.0; + + + if (t_tx > t_tx_max) + t_tx_max = t_tx; + if (t_tx < t_tx_min) + t_tx_min = t_tx; + if (t_rx > t_rx_max) + t_rx_max = t_rx; + if (t_rx < t_rx_min) + t_rx_min = t_rx; + if (t_tx > 2000) + n_tx_dropped++; + if (t_rx > 2000) + n_rx_dropped++; + + + push_front(&time_vector_tx, t_tx); + push_front(&time_vector_tx_ifft, t_tx_ifft); + push_front(&time_vector_tx_mod, t_tx_mod); + push_front(&time_vector_tx_enc, t_tx_enc); + + push_front(&time_vector_rx, t_rx); + push_front(&time_vector_rx_fft, t_rx_fft); + push_front(&time_vector_rx_demod, t_rx_demod); + push_front(&time_vector_rx_dec, t_rx_dec); + + + } //trials + +#ifdef DEBUG_HARQ + printf("\n both failed round 0 = %d, both failed round 1 = %d, both failed round 2 = %d, both failed round 3 = %d\n", resend_both[0], resend_both[1], resend_both[2], resend_both[3]); + printf(" only one failed round 0 = %d, only one failed round 1 = %d, only one failed round 2 = %d, only one failed round 3 = %d\n", resend_one[0], resend_one[1], resend_one[2], resend_one[3]); + if (rx_type == rx_SIC_dual_stream){ + printf(" sic attempt round 0 = %d, sic attempt round 1 = %d, sic attempt round 2 = %d, sic attempt round 3 = %d\n", sic_attempt[0], sic_attempt[1], sic_attempt[2], sic_attempt[3]); + printf(" decoded in sic round 0 = %d, decoded in sic round 1 = %d, decoded in sic round 2 = %d, decoded in sic round 3 = %d\n", decoded_in_sic[0], decoded_in_sic[1], decoded_in_sic[2], decoded_in_sic[3]); + } + else if (rx_type == rx_IC_dual_stream){ + printf(" TB0 deactiv round 0 = %d, TB0 deactiv round 1 = %d, TB0 deactiv round 2 = %d, TB0 deactiv round 3 = %d\n", TB0_deact[0], TB0_deact[1], TB0_deact[2], TB0_deact[3]); + printf(" TB1 deactiv round 0 = %d, TB1 deactiv round 1 = %d, TB1 deactiv round 2 = %d, TB1 deactiv round 3 = %d\n", TB1_deact[0], TB1_deact[1], TB1_deact[2], TB1_deact[3]); + } +#endif + // round_trials[0]: number of code word : goodput the protocol + double table_tx[time_vector_tx.size]; + totable(table_tx, &time_vector_tx); + double table_tx_ifft[time_vector_tx_ifft.size]; + totable(table_tx_ifft, &time_vector_tx_ifft); + double table_tx_mod[time_vector_tx_mod.size]; + totable(table_tx_mod, &time_vector_tx_mod); + double table_tx_enc[time_vector_tx_enc.size]; + totable(table_tx_enc, &time_vector_tx_enc); + + double table_rx[time_vector_rx.size]; + totable(table_rx, &time_vector_rx); + double table_rx_fft[time_vector_rx_fft.size]; + totable(table_rx_fft, &time_vector_rx_fft); + double table_rx_demod[time_vector_rx_demod.size]; + totable(table_rx_demod, &time_vector_rx_demod); + double table_rx_dec[time_vector_rx_dec.size]; + totable(table_rx_dec, &time_vector_rx_dec); + + + // sort table + qsort (table_tx, time_vector_tx.size, sizeof(double), &compare); + qsort (table_rx, time_vector_rx.size, sizeof(double), &compare); + + if (dump_table == 1 ) { + set_component_filelog(USIM); // file located in /tmp/usim.txt + int n; + LOG_F(USIM,"The transmitter raw data: \n"); + + for (n=0; n< time_vector_tx.size; n++) { + printf("%f ", table_tx[n]); + LOG_F(USIM,"%f ", table_tx[n]); + } + + LOG_F(USIM,"\n"); + LOG_F(USIM,"The receiver raw data: \n"); + + for (n=0; n< time_vector_rx.size; n++) { + // printf("%f ", table_rx[n]); + LOG_F(USIM,"%f ", table_rx[n]); + } + + LOG_F(USIM,"\n"); + } + + double tx_median = table_tx[time_vector_tx.size/2]; + double tx_q1 = table_tx[time_vector_tx.size/4]; + double tx_q3 = table_tx[3*time_vector_tx.size/4]; + + double tx_ifft_median = table_tx_ifft[time_vector_tx_ifft.size/2]; + double tx_ifft_q1 = table_tx_ifft[time_vector_tx_ifft.size/4]; + double tx_ifft_q3 = table_tx_ifft[3*time_vector_tx_ifft.size/4]; + + double tx_mod_median = table_tx_mod[time_vector_tx_mod.size/2]; + double tx_mod_q1 = table_tx_mod[time_vector_tx_mod.size/4]; + double tx_mod_q3 = table_tx_mod[3*time_vector_tx_mod.size/4]; + + double tx_enc_median = table_tx_enc[time_vector_tx_enc.size/2]; + double tx_enc_q1 = table_tx_enc[time_vector_tx_enc.size/4]; + double tx_enc_q3 = table_tx_enc[3*time_vector_tx_enc.size/4]; + + double rx_median = table_rx[time_vector_rx.size/2]; + double rx_q1 = table_rx[time_vector_rx.size/4]; + double rx_q3 = table_rx[3*time_vector_rx.size/4]; + + double rx_fft_median = table_rx_fft[time_vector_rx_fft.size/2]; + double rx_fft_q1 = table_rx_fft[time_vector_rx_fft.size/4]; + double rx_fft_q3 = table_rx_fft[3*time_vector_rx_fft.size/4]; + + double rx_demod_median = table_rx_demod[time_vector_rx_demod.size/2]; + double rx_demod_q1 = table_rx_demod[time_vector_rx_demod.size/4]; + double rx_demod_q3 = table_rx_demod[3*time_vector_rx_demod.size/4]; + + double rx_dec_median = table_rx_dec[time_vector_rx_dec.size/2]; + double rx_dec_q1 = table_rx_dec[time_vector_rx_dec.size/4]; + double rx_dec_q3 = table_rx_dec[3*time_vector_rx_dec.size/4]; + + double std_phy_proc_tx=0; + double std_phy_proc_tx_ifft=0; + double std_phy_proc_tx_mod=0; + double std_phy_proc_tx_enc=0; + + double std_phy_proc_rx=0; + double std_phy_proc_rx_fft=0; + double std_phy_proc_rx_demod=0; + double std_phy_proc_rx_dec=0; + + + if (transmission_mode != 3 && transmission_mode !=4) { + effective_rate = ((double)(round_trials[0][0]-dci_errors)/((double)round_trials[0][0] + round_trials[0][1] + round_trials[0][2] + round_trials[0][3])); + } + else { + effective_rate = ((double)(round_trials[0][0]-dci_errors)/((double)round_trials[0][0] + round_trials[0][1] + round_trials[0][2] + round_trials[0][3]))+ + ((double)(round_trials[1][0])/((double)round_trials[1][0] + round_trials[1][1] + round_trials[1][2] + round_trials[1][3])); + } + + /* + Here we compute throughput per cw based on the formula + T=P_suc[r1]R(mcs) + sum[r=2 ..r=4] (P_(suc r, fail r-1)*R/r). + The non-constr formula should not be used, when there are some errors on the last round, + meaning when not all the packages are finally decoded. + */ + + if (transmission_mode == 3 || transmission_mode == 4) { + // FOR CW0 + thr_cw0[0] = rate0_init*get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs)*(1-((double)errs[0][0]/(double)round_trials[0][0])); + if (num_rounds > 1) + thr_cw0[1] = (rate0_init*get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs)/2)*(((double)errs[0][0] - (double)errs[0][1])/(double)round_trials[0][0]); + else + thr_cw0[1]=0; + if (num_rounds > 2) + thr_cw0[2] = (rate0_init*get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs)/3)*(((double)errs[0][1] - (double)errs[0][2])/(double)round_trials[0][0]); + else + thr_cw0[2]=0; + if (num_rounds > 3) + thr_cw0[3] = (rate0_init*get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs)/4)*(((double)errs[0][2] - (double)errs[0][3])/(double)round_trials[0][0]); + else + thr_cw0[3]=0; + thr_cw0_tot = (double)thr_cw0[0]+(double)thr_cw0[1]+(double)thr_cw0[2]+(double)thr_cw0[3]; +#ifdef PRINT_THROUGHPUT + printf("rate %f \n", rate0_init); + printf("rate*mod_order %f \n", rate0_init*get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs)); + printf("Probability %f \n", (1-((double)errs[0][0]/(double)round_trials[0][0]))); + printf("Throughput cw0 sum = %f \n", thr_cw0_tot); + printf("Throughput cw0 round 0 = %f \n", thr_cw0[0]); + printf("Throughput cw0 round 1 = %f \n", thr_cw0[1]); + printf("Throughput cw0 round 2 = %f \n", thr_cw0[2]); + printf("Throughput cw0 round 3 = %f \n", thr_cw0[3]); + printf("round_trials = %d, errs[0][0] = %d, round_trials[0][1] = %d, errs[0][1] = %d, round_trials[0][2] = %d, errs[0][2] = %d, \ + round_trials[0][3] = %d, errs[0][3] = %d \n", round_trials[0][0], errs[0][0],round_trials[0][1], errs[0][1], round_trials[0][2], \ + errs[0][2], round_trials[0][3], errs[0][3]); +#endif + + thr_cw1[0] = rate1_init*get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs)*(1-((double)errs[1][0]/(double)round_trials[1][0])); + if (num_rounds > 1) + thr_cw1[1] = (rate1_init*get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs)/2)*(((double)errs[1][0] - (double)errs[1][1])/(double)round_trials[1][0]); + else + thr_cw1[1] = 0; + if (num_rounds > 2) + thr_cw1[2] = (rate1_init*get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs)/3)*(((double)errs[1][1] - (double)errs[1][2])/(double)round_trials[1][0]); + else + thr_cw1[2] = 0; + if (num_rounds > 3) + thr_cw1[3] = (rate1_init*get_Qm(eNB->dlsch[0][1]->harq_processes[0]->mcs)/4)*(((double)errs[1][2] - (double)errs[1][3])/(double)round_trials[1][0]); + else + thr_cw1[3]=0; + thr_cw1_tot = (double)thr_cw1[0]+(double)thr_cw1[1]+(double)thr_cw1[2]+(double)thr_cw1[3]; +#ifdef PRINT_THROUGHPUT + printf("Throughput cw1 sum = %f \n", thr_cw1_tot); + printf("Throughput cw1 round 0 = %f \n", thr_cw1[0]); + printf("Throughput cw1 round 1 = %f \n", thr_cw1[1]); + printf("Throughput cw1 round 2 = %f \n", thr_cw1[2]); + printf("Throughput cw1 round 3 = %f \n", thr_cw1[3]); + printf("round_trials[1][0] = %d, errs[1][0] = %d, round_trials[1][1] = %d, errs[1][1] = %d, round_trials[1][2] = %d, errs[1][2] = %d, \ + round_trials[1][3] = %d, errs[1][3] = %d \n", round_trials[1][0], errs[1][0], round_trials[1][1], errs[1][1], round_trials[1][2], \ + errs[1][2], round_trials[1][3], errs[1][3]); +#endif + } + +#if 0 + thr_cw0_tm4_nonconst = rate[0]*get_Qm(PHY_vars_eNB->dlsch[0][0]->harq_processes[0]->mcs)* \ + ((double)(round_trials[0][0]-dci_errors)/((double)round_trials[0][0] + round_trials[0][1] + round_trials[0][2] + round_trials[0][3])); + printf("Throughput cw0 noncnstr = %f \n", thr_cw0_tm4_nonconst); +#endif + //FOR CW1 + /*thr_cw1[0] = rate[1]*get_Qm(PHY_vars_eNB->dlsch[0][1]->harq_processes[0]->mcs)*(1-((double)errs[0][0]/(double)round_trials[0][0])) \ + *(1-((double)errs[1][0]/(double)round_trials[1][0])); + printf("thr cw1 round 0 = %f\n", thr_cw1[0]); + thr_cw1[1]=(rate[1]*get_Qm(PHY_vars_eNB->dlsch[0][1]->harq_processes[0]->mcs)/2)*\ + (((double)errs[1][0]-(double)errs[1][1])*((double)round_trials[0][0] - (double)errs[0][1])/((double)round_trials[0][0]*(double)round_trials[1][0])); + printf("thr cw1 round 1 = %f\n", thr_cw1[1]); + thr_cw1[2] = (rate[0]*get_Qm(PHY_vars_eNB->dlsch[0][0]->harq_processes[0]->mcs)/3)*\ + ((double)errs[1][1]-(double)errs[1][2])*((double)round_trials[0][0]-(double)errs[0][2])/((double)round_trials[0][0]*(double)round_trials[1][0]); + printf("thr cw1 round 2 = %f\n", thr_cw1[2]); + thr_cw1[3] = (rate[0]*get_Qm(PHY_vars_eNB->dlsch[0][0]->harq_processes[0]->mcs)/4)*\ + ((double)errs[1][2]-(double)errs[1][3])*((double)round_trials[0][0] - (double)errs[0][3])/((double)round_trials[0][0]*(double)round_trials[1][0]); + resid_errs= + printf("thr cw1 round 3 = %f\n", thr_cw1[3]); + thr_cw1_tot =thr_cw1[0]+thr_cw1[1]+thr_cw1[2]+thr_cw1[3]; + printf("Throughput cw1 sum = %f \n", thr_cw1_tot); + printf("round_trials = %d, errs[1][0] = %d, round_trials[1][1] = %d, errs[1][1] = %d, round_trials[1][2] = %d, errs[1][2] = %d, \ + round_trials[1][3] = %d, errs[1][3] = %d \n", round_trials[1][0], errs[1][0],round_trials[1][1], errs[1][1], round_trials[1][2], \ + errs[1][2], round_trials[1][3], errs[1][3]); + }*/ + + + printf("\n**********************SNR = %f dB (tx_lev %f, sigma2_dB %f)**************************\n", + SNR, + (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12)), + sigma2_dB); + if ((transmission_mode != 3) && (transmission_mode != 4)){ + printf("Errors (%d(%d)/%d %d(%d)/%d %d(%d)/%d %d(%d)/%d), Pe = (%e(%e),%e(%e),%e(%e),%e(%e))," + "dci_errors %d/%d, Pe = %e => effective rate %f (%2.1f%%,%f, %f), normalized delay %f (%f), " + "throughput stream 0 = %f , throughput stream 1 = %f, system throughput = %f , rate 0 = %f , rate 1 = %f \n", + errs[0][0], + errs[1][0], + round_trials[0][0], + errs[0][1], + errs[1][1], + round_trials[0][0], + errs[0][2], + errs[1][2], + round_trials[0][0], + errs[0][3], + errs[1][3], + round_trials[0][0], + (double)errs[0][0]/(round_trials[0][0]), + (double)errs[1][0]/(round_trials[0][0]), + (double)errs[0][1]/(round_trials[0][0]), + (double)errs[1][1]/(round_trials[0][0]), + (double)errs[0][2]/(round_trials[0][0]), + (double)errs[1][2]/(round_trials[0][0]), + (double)errs[0][3]/(round_trials[0][0]), + (double)errs[1][3]/(round_trials[0][0]), + dci_errors, + round_trials[0][0], + (double)dci_errors/(round_trials[0][0]), + rate[0]*effective_rate, + 100*effective_rate, + rate[0], + rate[0]*get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), + (1.0*(round_trials[0][0]-errs[0][0])+2.0*(round_trials[0][1]-errs[0][1])+3.0*(round_trials[0][2]-errs[0][2])+ + 4.0*(round_trials[0][3]-errs[0][3]))/((double)round_trials[0][0])/(double)eNB->dlsch[0][0]->harq_processes[0]->TBS, + (1.0*(round_trials[0][0]-errs[0][0])+2.0*(round_trials[0][1]-errs[0][1])+3.0*(round_trials[0][2]-errs[0][2]) + +4.0*(round_trials[0][3]-errs[0][3]))/((double)round_trials[0][0]), + thr_cw0_tot, + thr_cw1_tot, + thr_cw0_tot + thr_cw1_tot, + rate[0], + rate[1]); + }else{ + printf("Errors (%d(%d)/%d %d(%d)/%d %d(%d)/%d %d(%d)/%d)," + "dci_errors %d/%d, thr TB0 = %f , thr TB1 = %f, overall thr = %f , rate 0 = %f , rate 1 = %f \n", + errs[0][0], + errs[1][0], + round_trials[0][0], + errs[0][1], + errs[1][1], + round_trials[0][0], + errs[0][2], + errs[1][2], + round_trials[0][0], + errs[0][3], + errs[1][3], + round_trials[0][0], + dci_errors, + round_trials[0][0], + thr_cw0_tot, + thr_cw1_tot, + thr_cw0_tot + thr_cw1_tot, + rate0_init, + rate1_init); + } + + if (print_perf==1) { + printf("eNB TX function statistics (per 1ms subframe)\n\n"); + std_phy_proc_tx = sqrt((double)eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->phy_proc_tx.trials - pow((double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc tx :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials); + printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, + n_tx_dropped); + std_phy_proc_tx_ifft = sqrt((double)eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->ofdm_mod_stats.trials - pow((double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2)); + printf("OFDM_mod time :%f us (%d trials)\n",(double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,eNB->ofdm_mod_stats.trials); + printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3); + std_phy_proc_tx_mod = sqrt((double)eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->dlsch_modulation_stats.trials - pow((double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH modulation time :%f us (%d trials)\n",(double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0, + eNB->dlsch_modulation_stats.trials); + printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3); + printf("DLSCH scrambling time :%f us (%d trials)\n",(double)eNB->dlsch_scrambling_stats.diff/eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0, + eNB->dlsch_scrambling_stats.trials); + std_phy_proc_tx_enc = sqrt((double)eNB->dlsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->dlsch_encoding_stats.trials - pow((double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH encoding time :%f us (%d trials)\n",(double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000.0, + eNB->dlsch_modulation_stats.trials); + printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3); + printf("|__ DLSCH turbo encoding time :%f us (%d trials)\n", + ((double)eNB->dlsch_turbo_encoding_stats.trials/eNB->dlsch_encoding_stats.trials)*(double) + eNB->dlsch_turbo_encoding_stats.diff/eNB->dlsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_turbo_encoding_stats.trials); + printf("|__ DLSCH rate-matching time :%f us (%d trials)\n", + ((double)eNB->dlsch_rate_matching_stats.trials/eNB->dlsch_encoding_stats.trials)*(double) + eNB->dlsch_rate_matching_stats.diff/eNB->dlsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_rate_matching_stats.trials); + printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n", + ((double)eNB->dlsch_interleaving_stats.trials/eNB->dlsch_encoding_stats.trials)*(double) + eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials); + + printf("\n\nUE RX function statistics (per 1ms subframe)\n\n"); + std_phy_proc_rx = sqrt((double)UE->phy_proc_rx[subframe&0x1].diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->phy_proc_rx[subframe&0x1].trials - pow((double)UE->phy_proc_rx[subframe&0x1].diff/UE->phy_proc_rx[subframe&0x1].trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx[subframe&0x1].diff/UE->phy_proc_rx[subframe&0x1].trials/cpu_freq_GHz/1000.0, + UE->phy_proc_rx[subframe&0x1].trials*2/3); + printf("|__Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, + rx_q1, rx_q3, n_rx_dropped); + std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->ofdm_demod_stats.trials - pow((double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0, + UE->ofdm_demod_stats.trials*2/3); + printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3); + printf("|__ DLSCH rx dft :%f us (%d trials)\n", + (nsymb*UE->frame_parms.nb_antennas_rx)*(double)UE->rx_dft_stats.diff/UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,UE->rx_dft_stats.trials*2/3); + printf("|__ DLSCH channel estimation time :%f us (%d trials)\n", + (4.0)*(double)UE->dlsch_channel_estimation_stats.diff/UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_channel_estimation_stats.trials*2/3); + printf("|__ DLSCH frequency offset estimation time :%f us (%d trials)\n", + (4.0)*(double)UE->dlsch_freq_offset_estimation_stats.diff/UE->dlsch_freq_offset_estimation_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_freq_offset_estimation_stats.trials*2/3); + printf("DLSCH rx pdcch :%f us (%d trials)\n",(double)UE->dlsch_rx_pdcch_stats.diff/UE->dlsch_rx_pdcch_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_rx_pdcch_stats.trials); + std_phy_proc_rx_demod = sqrt((double)UE->dlsch_llr_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->dlsch_llr_stats.trials - pow((double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH Channel Compensation and LLR generation time :%f us (%d trials)\n",(3)*(double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_llr_stats.trials/3); + printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3); + printf("DLSCH unscrambling time :%f us (%d trials)\n",(double)UE->dlsch_unscrambling_stats.diff/UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_unscrambling_stats.trials); + std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats[subframe&0x1].diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->dlsch_decoding_stats[subframe&0x1].trials - pow((double)UE->dlsch_decoding_stats[subframe&0x1].diff/UE->dlsch_decoding_stats[subframe&0x1].trials/cpu_freq_GHz/1000,2)); + printf("DLSCH Decoding time (%02.2f Mbit/s, avg iter %1.2f) :%f us (%d trials, max %f)\n", + eNB->dlsch[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter[0]/iter_trials[0], + (double)UE->dlsch_decoding_stats[subframe&0x1].diff/UE->dlsch_decoding_stats[subframe&0x1].trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats[subframe&0x1].trials, + (double)UE->dlsch_decoding_stats[subframe&0x1].max/cpu_freq_GHz/1000.0); + printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3); + printf("|__ DLSCH Rate Unmatching :%f us (%d trials)\n", + (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials); + printf("|__ DLSCH Turbo Decoding(%d bits) :%f us (%d trials)\n", + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Cminus ? UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kminus : UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kplus, + (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials); + printf(" |__ init %f us (cycles/iter %f, %d trials)\n", + (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/((double)avg_iter[0]/iter_trials[0]), + UE->dlsch_tc_init_stats.trials); + printf(" |__ alpha %f us (cycles/iter %f, %d trials)\n", + (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials*2, + UE->dlsch_tc_alpha_stats.trials); + printf(" |__ beta %f us (cycles/iter %f,%d trials)\n", + (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials*2, + UE->dlsch_tc_beta_stats.trials); + printf(" |__ gamma %f us (cycles/iter %f,%d trials)\n", + (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials*2, + UE->dlsch_tc_gamma_stats.trials); + printf(" |__ ext %f us (cycles/iter %f,%d trials)\n", + (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials*2, + UE->dlsch_tc_ext_stats.trials); + printf(" |__ intl1 %f us (cycles/iter %f,%d trials)\n", + (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials, + UE->dlsch_tc_intl1_stats.trials); + printf(" |__ intl2+HD+CRC %f us (cycles/iter %f,%d trials)\n", + (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials, + UE->dlsch_tc_intl2_stats.trials); + } + + if ((transmission_mode != 3) && (transmission_mode != 4)) { + fprintf(bler_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n", + SNR, + mcs1, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + rate[0], + errs[0][0], + round_trials[0][0], + errs[0][1], + round_trials[0][1], + errs[0][2], + round_trials[0][2], + errs[0][3], + round_trials[0][3], + dci_errors); + } + else if ( rx_type== rx_SIC_dual_stream) { + fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f\n", + SNR, + mcs1, + mcs2, + tbs0_init, + tbs1_init, + rate0_init, + rate1_init, + errs[0][0], + errs[1][0], + round_trials[0][0], + round_trials[1][0], + sic_attempt[0], + decoded_in_sic[0], + resend_both[0], + resend_one[0], + errs[0][1], + errs[1][1], + round_trials[0][1], + round_trials[1][1], + sic_attempt[1], + decoded_in_sic[1], + resend_both[1], + resend_one[1], + errs[0][2], + errs[1][2], + round_trials[0][2], + round_trials[1][2], + sic_attempt[2], + decoded_in_sic[2], + resend_both[2], + resend_one[2], + errs[0][3], + errs[1][3], + round_trials[0][3], + round_trials[1][3], + sic_attempt[3], + decoded_in_sic[3], + thr_cw0[0], + thr_cw1[0], + thr_cw0[0]+thr_cw1[0], + thr_cw0[1], + thr_cw1[1], + thr_cw0[1]+thr_cw1[1], + thr_cw0[2], + thr_cw1[2], + thr_cw0[2]+thr_cw1[2], + thr_cw0[3], + thr_cw1[3], + thr_cw0[3]+thr_cw1[3], + thr_cw0[0]+thr_cw0[1]+thr_cw0[2]+thr_cw0[3]+thr_cw1[0]+thr_cw1[1]+thr_cw1[2]+ thr_cw1[3]); + } + else{ + fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f\n", + SNR, + mcs1, + mcs2, + tbs0_init, + tbs1_init, + rate0_init, + rate1_init, + errs[0][0], + errs[1][0], + round_trials[0][0], + round_trials[1][0], + TB0_deact[0], + TB1_deact[0], + resend_both[0], + resend_one[0], + errs[0][1], + errs[1][1], + round_trials[0][1], + round_trials[1][1], + TB0_deact[1], + TB1_deact[1], + resend_both[1], + resend_one[1], + errs[0][2], + errs[1][2], + round_trials[0][2], + round_trials[1][2], + TB0_deact[2], + TB1_deact[2], + resend_both[2], + resend_one[2], + errs[0][3], + errs[1][3], + round_trials[0][3], + round_trials[1][3], + thr_cw0[0], + thr_cw1[0], + thr_cw0[0]+thr_cw1[0], + thr_cw0[1], + thr_cw1[1], + thr_cw0[1]+thr_cw1[1], + thr_cw0[2], + thr_cw1[2], + thr_cw0[2]+thr_cw1[2], + thr_cw0[3], + thr_cw1[3], + thr_cw0[3]+thr_cw1[3], + thr_cw0[0]+thr_cw0[1]+thr_cw0[2]+thr_cw0[3]+thr_cw1[0]+thr_cw1[1]+thr_cw1[2]+ thr_cw1[3]); + } + + + if(abstx){ //ABSTRACTION + if ((transmission_mode != 3)&& (transmission_mode != 4)) { + + blerr[0][0] = (double)errs[0][0]/(round_trials[0][0]); + + if(num_rounds>1){ + blerr[0][1] = (double)errs[0][1]/(round_trials[0][1]); + + blerr[0][2] = (double)errs[0][2]/(round_trials[0][2]); + + blerr[0][3] = (double)errs[0][3]/(round_trials[0][3]); + + fprintf(csv_fd,"%e;%e;%e;%e;\n",blerr[0][0],blerr[0][1],blerr[0][2],blerr[0][3]); + } + else { + fprintf(csv_fd,"%e;\n",blerr[0][0]); + } + } + else { + blerr[0][0] = (double)errs[0][0]/(round_trials[0][0]); + blerr[1][0] = (double)errs[1][0]/(round_trials[0][0]); + if(num_rounds>1){ + blerr[0][1] = (double)errs[0][1]/(round_trials[0][1]); + blerr[1][1] = (double)errs[1][1]/(round_trials[1][1]); + blerr[0][2] = (double)errs[0][2]/(round_trials[0][2]); + blerr[1][2] = (double)errs[1][2]/(round_trials[1][2]); + blerr[0][3] = (double)errs[0][3]/(round_trials[0][3]); + blerr[1][3] = (double)errs[1][3]/(round_trials[1][3]); + + fprintf(csv_fd,"%e;%e;%e;%e;%e;%e;%e;%e;\n",blerr[0][0],blerr[1][0],blerr[0][1],blerr[1][1],blerr[0][2],blerr[1][2], blerr[0][3], blerr[1][3]); + } + else { + fprintf(csv_fd,"%e,%e;\n",blerr[0][0], blerr[1][0]); + } + } + } + + if ( (test_perf != 0) && (100 * effective_rate > test_perf )) { + //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n"); + if ((transmission_mode != 3) && (transmission_mode != 4)) { + fprintf(time_meas_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;", + SNR, + mcs1, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + rate[0], + errs[0][0], + round_trials[0][0], + errs[0][1], + round_trials[0][1], + errs[0][2], + round_trials[0][2], + errs[0][3], + round_trials[0][3], + dci_errors); + + //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); + fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", + SNR, + mcs1, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + rate[0]*effective_rate, + 100*effective_rate, + rate[0], + (double)avg_iter[0]/iter_trials[0], + errs[0][0], + round_trials[0], + errs[0][1], + round_trials[1], + errs[0][2], + round_trials[2], + errs[0][3], + round_trials[3], + (double)errs[0][0]/(round_trials[0][0]), + (double)errs[0][1]/(round_trials[0][0]), + (double)errs[0][2]/(round_trials[0][0]), + (double)errs[0][3]/(round_trials[0][0]), + dci_errors, + round_trials[0], + (double)dci_errors/(round_trials[0][0]), + (1.0*(round_trials[0][0]-errs[0][0])+2.0*(round_trials[0][1]-errs[0][1])+3.0*(round_trials[0][2]-errs[0][2])+4.0*(round_trials[0][3]-errs[0][3]))/((double)round_trials[0][0])/(double)eNB->dlsch[0][0]->harq_processes[0]->TBS, + (1.0*(round_trials[0][0]-errs[0][0])+2.0*(round_trials[0][1]-errs[0][1])+3.0*(round_trials[0][2]-errs[0][2])+4.0*(round_trials[0][3]-errs[0][3]))/((double)round_trials[0][0])); + } + else { + fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;", + SNR, + mcs1,mcs2, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, + rate[0], + errs[0][0], + round_trials[0][0], + errs[0][1], + round_trials[0][1], + errs[0][2], + round_trials[0][2], + errs[0][3], + round_trials[0][3], + dci_errors); + + //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); + fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", + SNR, + mcs1,mcs2, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, + rate[0]*effective_rate, + 100*effective_rate, + rate[0], + (double)avg_iter[0]/iter_trials[0], + errs[0][0], + round_trials[0][0], + errs[0][1], + round_trials[0][1], + errs[0][2], + round_trials[0][2], + errs[0][3], + round_trials[3], + (double)errs[0][0]/(round_trials[0][0]), + (double)errs[0][1]/(round_trials[0][0]), + (double)errs[0][2]/(round_trials[0][0]), + (double)errs[0][3]/(round_trials[0][0]), + dci_errors, + round_trials[0][0], + (double)dci_errors/(round_trials[0][0]), + (1.0*(round_trials[0][0]-errs[0][0])+2.0*(round_trials[0][1]-errs[0][1])+3.0*(round_trials[0][2]-errs[0][2])+4.0*(round_trials[0][3]-errs[0][3]))/((double)round_trials[0][0])/(double)eNB->dlsch[0][0]->harq_processes[0]->TBS, + (1.0*(round_trials[0][0]-errs[0][0])+2.0*(round_trials[0][1]-errs[0][1])+3.0*(round_trials[0][2]-errs[0][2])+4.0*(round_trials[0][3]-errs[0][3]))/((double)round_trials[0][0])); + } + //fprintf(time_meas_fd,"eNB_PROC_TX(%d); OFDM_MOD(%d); DL_MOD(%d); DL_SCR(%d); DL_ENC(%d); UE_PROC_RX(%d); OFDM_DEMOD_CH_EST(%d); RX_PDCCH(%d); CH_COMP_LLR(%d); DL_USCR(%d); DL_DECOD(%d);\n", + fprintf(time_meas_fd,"%d; %d; %d; %d; %d; %d; %d; %d; %d; %d; %d;", + eNB->phy_proc_tx.trials, + eNB->ofdm_mod_stats.trials, + eNB->dlsch_modulation_stats.trials, + eNB->dlsch_scrambling_stats.trials, + eNB->dlsch_encoding_stats.trials, + UE->phy_proc_rx[subframe&0x1].trials, + UE->ofdm_demod_stats.trials, + UE->dlsch_rx_pdcch_stats.trials, + UE->dlsch_llr_stats.trials, + UE->dlsch_unscrambling_stats.trials, + UE->dlsch_decoding_stats[subframe&0x1].trials + ); + fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;", + get_time_meas_us(&eNB->phy_proc_tx), + get_time_meas_us(&eNB->ofdm_mod_stats), + get_time_meas_us(&eNB->dlsch_modulation_stats), + get_time_meas_us(&eNB->dlsch_scrambling_stats), + get_time_meas_us(&eNB->dlsch_encoding_stats), + get_time_meas_us(&UE->phy_proc_rx[subframe&0x1]), + nsymb*get_time_meas_us(&UE->ofdm_demod_stats), + get_time_meas_us(&UE->dlsch_rx_pdcch_stats), + 3*get_time_meas_us(&UE->dlsch_llr_stats), + get_time_meas_us(&UE->dlsch_unscrambling_stats), + get_time_meas_us(&UE->dlsch_decoding_stats[subframe&0x1]) + ); + //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); + + //fprintf(time_meas_fd,"IFFT;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3); + + //fprintf(time_meas_fd,"MOD;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3); + + //fprintf(time_meas_fd,"ENC;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3); + + + //fprintf(time_meas_fd,"UE_PROC_RX_STD;UE_PROC_RX_MAX;UE_PROC_RX_MIN;UE_PROC_RX_MED;UE_PROC_RX_Q1;UE_PROC_RX_Q3;UE_PROC_RX_DROPPED;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); + + //fprintf(time_meas_fd,"FFT;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3); + + //fprintf(time_meas_fd,"DEMOD;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_demod,rx_demod_median, rx_demod_q1, rx_demod_q3); + + //fprintf(time_meas_fd,"DEC;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f\n", std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3); + + + /* + fprintf(time_meas_fd,"%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;", + eNB->phy_proc_tx.trials, + eNB->ofdm_mod_stats.trials, + eNB->dlsch_modulation_stats.trials, + eNB->dlsch_scrambling_stats.trials, + eNB->dlsch_encoding_stats.trials, + UE->phy_proc_rx.trials, + UE->ofdm_demod_stats.trials, + UE->dlsch_rx_pdcch_stats.trials, + UE->dlsch_llr_stats.trials, + UE->dlsch_unscrambling_stats.trials, + UE->dlsch_decoding_stats[subframe&0x1].trials); + */ + printf("[passed] effective rate : %f (%2.1f%%,%f)): log and break \n",rate[0]*effective_rate, 100*effective_rate, rate[0]); + break; + } else if (test_perf !=0 ){ + printf("[continue] effective rate : %f (%2.1f%%,%f)): increase snr \n",rate[0]*effective_rate, 100*effective_rate, rate[0]); + } + if (abstx == 1) { + if ((rx_type==rx_IC_dual_stream) || (rx_type==rx_SIC_dual_stream)) { + + if ((((double)errs[0][0]/(round_trials[0][0]))<1e-2) && (((double)errs[1][0]/(round_trials[1][0]))<1e-2)) + if ((((double)errs[0][0]/(round_trials[0][0]))<1e-2) && (((double)errs[1][0]/(round_trials[1][0]))<1e-2)) + break; + } + else{ + if (((double)errs[0][0]/(round_trials[0][0]))<1e-2) + break; + + } + } + else { + + if ((rx_type==rx_IC_dual_stream) || (rx_type==rx_SIC_dual_stream)) { + if ((((double)errs[0][0]/(round_trials[0][0]))<1e-3) && (((double)errs[1][0]/(round_trials[1][0]))<1e-3)) + break; + } + else{ + if (((double)errs[0][0]/(round_trials[0][0]))<1e-3) + break; + + } + + } + + if (n_frames==1) + break; + + }// SNR + + } //ch_realization + + fclose(bler_fd); + + if (test_perf !=0) + fclose (time_meas_fd); + + //fprintf(tikz_fd,"};\n"); + //fclose(tikz_fd); + + if (input_trch_file==1) + fclose(input_trch_fd); + + if (input_file==1) + fclose(input_fd); + + if(abstx) { // ABSTRACTION + fprintf(csv_fd,"];"); + fclose(csv_fd); + } + + if (uncoded_ber_bit) + free(uncoded_ber_bit); + + uncoded_ber_bit = NULL; + + for (k=0; k<n_users; k++) { + free(input_buffer0[k]); + free(input_buffer1[k]); + input_buffer0[k]=NULL; + input_buffer1[k]=NULL; + } + + printf("Freeing dlsch structures\n"); + + for (i=0; i<2; i++) { + printf("eNB %d\n",i); + + free_eNB_dlsch(eNB->dlsch[0][i]); + printf("UE %d\n",i); + free_ue_dlsch(UE->dlsch[subframe&0x1][0][i]); + } + + + printf("Freeing channel I/O\n"); + + for (i=0; i<2; i++) { + free(s_re[i]); + free(s_im[i]); + free(r_re[i]); + free(r_im[i]); + } + + free(s_re); + free(s_im); + free(r_re); + free(r_im); + + // lte_sync_time_free(); + + // printf("[MUMIMO] mcs %d, mcsi %d, offset %d, bler %f\n",mcs,mcs_i,offset_mumimo_llr_drange_fix,((double)errs[0])/((double)round_trials[0])); + + return(0); +} + + diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c index 874af41f45c3c4cb9cb951c6eb543f0503a47f6f..3055e99b07272a4d318787f4b6830b772efd88d8 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c @@ -1,31 +1,23 @@ - /****************************************************************************** - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see <http://www.gnu.org/licenses/>. - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ +/* + * 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.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.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 dlsim.c \brief Top-level DL simulator @@ -961,14 +953,14 @@ int main(int argc, char **argv) } for (i=0; i<2; i++) { - UE->dlsch[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->dlsch[subframe&0x1][0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); - if (!UE->dlsch[0][i]) { + if (!UE->dlsch[subframe&0x1][0][i]) { printf("Can't get ue dlsch structures\n"); exit(-1); } - UE->dlsch[0][i]->rnti = n_rnti; + UE->dlsch[subframe&0x1][0][i]->rnti = n_rnti; } // structure for SIC at UE @@ -2077,7 +2069,7 @@ int main(int argc, char **argv) reset_meas(&eNB->dlsch_rate_matching_stats); reset_meas(&eNB->dlsch_turbo_encoding_stats); - reset_meas(&UE->phy_proc_rx); // total UE rx + reset_meas(&UE->phy_proc_rx[subframe&0x1]); // total UE rx reset_meas(&UE->ofdm_demod_stats); reset_meas(&UE->dlsch_channel_estimation_stats); reset_meas(&UE->dlsch_freq_offset_estimation_stats); @@ -2120,9 +2112,9 @@ int main(int argc, char **argv) //if (trials%100==0) eNB2UE[0]->first_run = 1; - ret = UE->dlsch[0][0]->max_turbo_iterations+1; + ret = UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations+1; - while ((round < num_rounds) && (ret > UE->dlsch[0][0]->max_turbo_iterations)) { + while ((round < num_rounds) && (ret > UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations)) { //printf("Trial %d, round %d\n",trials,round); round_trials[round]++; @@ -2609,7 +2601,7 @@ PMI_FEEDBACK: // use the PMI from previous trial if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); - UE->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); if (n_users>1) eNB->dlsch[1][0]->harq_processes[0]->pmi_alloc = (eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555); @@ -3067,7 +3059,7 @@ PMI_FEEDBACK: } - start_meas(&UE->phy_proc_rx); + start_meas(&UE->phy_proc_rx[subframe&0x1]); // Inner receiver scheduling for 3 slots @@ -3235,7 +3227,7 @@ PMI_FEEDBACK: for (i=0; i<dci_cnt; i++) { // printf("Generating dlsch parameters for RNTI %x\n",dci_alloc_rx[i].rnti); - if (round == 0) UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->first_tx=1; + if (round == 0) UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->first_tx=1; if ((dci_alloc_rx[i].rnti == n_rnti) && (generate_ue_dlsch_params_from_dci(0, @@ -3243,7 +3235,7 @@ PMI_FEEDBACK: dci_alloc_rx[i].dci_pdu, dci_alloc_rx[i].rnti, dci_alloc_rx[i].format, - UE->dlsch[0], + UE->dlsch[subframe&0x1][0], &UE->frame_parms, UE->pdsch_config_dedicated, SI_RNTI, @@ -3252,23 +3244,23 @@ PMI_FEEDBACK: transmission_mode<7?0:transmission_mode))) { //dump_dci(&UE->frame_parms,&dci_alloc_rx[i]); coded_bits_per_codeword = get_G(&eNB->frame_parms, - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->nb_rb, - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->rb_alloc_even, - get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs), - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->Nl, + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->nb_rb, + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->rb_alloc_even, + get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->Nl, UE->pdcch_vars[0]->num_pdcch_symbols, 0, subframe, (transmission_mode<7?0:transmission_mode)); /*if (transmission_mode==7 && common_flag==0) - UE->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7; */ + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->mimo_mode = TM7; */ /* - rate = (double)dlsch_tbs25[get_I_TBS(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs)][UE->dlsch[0][0]->nb_rb-1]/(coded_bits_per_codeword); - rate*=get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs); + rate = (double)dlsch_tbs25[get_I_TBS(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs)][UE->dlsch[subframe&0x1][0][0]->nb_rb-1]/(coded_bits_per_codeword); + rate*=get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs); */ printf("num_pdcch_symbols %d, G %d, TBS %d\n",UE->pdcch_vars[0]->num_pdcch_symbols,coded_bits_per_codeword, - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->TBS); + UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->TBS); dlsch_active = 1; } else { @@ -3296,7 +3288,7 @@ PMI_FEEDBACK: UE->pdcch_vars[0]->crnti = n_rnti; UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; - if (round == 0) UE->dlsch[0][0]->harq_processes[0]->first_tx=1; + if (round == 0) UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx=1; switch (transmission_mode) { case 1: @@ -3307,7 +3299,7 @@ PMI_FEEDBACK: &DLSCH_alloc_pdu_1[0], (common_flag==0)? C_RNTI : SI_RNTI, (common_flag==0)? format1 : format1A, - UE->dlsch[0], + UE->dlsch[subframe&0x1][0], &UE->frame_parms, UE->pdsch_config_dedicated, SI_RNTI, @@ -3315,24 +3307,24 @@ PMI_FEEDBACK: P_RNTI, transmission_mode<7?0:transmission_mode); /*if(transmission_mode==7 && common_flag==0) - UE->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7;*/ + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->mimo_mode = TM7;*/ break; case 3: - // printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx); + // printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx); generate_ue_dlsch_params_from_dci(0, subframe, &DLSCH_alloc_pdu_1[0], (common_flag==0)? C_RNTI : SI_RNTI, (common_flag==0)? format2A : format1A, - UE->dlsch[0], + UE->dlsch[subframe&0x1][0], &UE->frame_parms, UE->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, 0); - // printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx); + // printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->round,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->first_tx); break; case 4: @@ -3341,7 +3333,7 @@ PMI_FEEDBACK: &DLSCH_alloc_pdu_1[0], (common_flag==0)? C_RNTI : SI_RNTI, (common_flag==0)? format2 : format1A, - UE->dlsch[0], + UE->dlsch[subframe&0x1][0], &UE->frame_parms, UE->pdsch_config_dedicated, SI_RNTI, @@ -3357,7 +3349,7 @@ PMI_FEEDBACK: &DLSCH_alloc_pdu2_1E[0], C_RNTI, format1E_2A_M10PRB, - UE->dlsch[0], + UE->dlsch[subframe&0x1][0], &UE->frame_parms, UE->pdsch_config_dedicated, SI_RNTI, @@ -3389,7 +3381,7 @@ PMI_FEEDBACK: if ((Ns==(1+(2*subframe))) && (l==0)) {// process PDSCH symbols 1,2,3,4,5,(6 Normal Prefix) if ((transmission_mode == 5) && - (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->dl_power_off==0) && + (UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->dl_power_off==0) && (UE->use_ia_receiver ==1)) { dual_stream_UE = 1; } else { @@ -3412,7 +3404,7 @@ PMI_FEEDBACK: (m==UE->pdcch_vars[0]->num_pdcch_symbols)?1:0, dual_stream_UE, i_mod, - UE->dlsch[0][0]->current_harq_pid)==-1) { + UE->dlsch[subframe&0x1][0][0]->current_harq_pid)==-1) { dlsch_active = 0; break; } @@ -3438,7 +3430,7 @@ PMI_FEEDBACK: 0, dual_stream_UE, i_mod, - UE->dlsch[0][0]->current_harq_pid)==-1) { + UE->dlsch[subframe&0x1][0][0]->current_harq_pid)==-1) { dlsch_active=0; break; } @@ -3464,7 +3456,7 @@ PMI_FEEDBACK: 0, dual_stream_UE, i_mod, - UE->dlsch[0][0]->current_harq_pid)==-1) { + UE->dlsch[subframe&0x1][0][0]->current_harq_pid)==-1) { dlsch_active=0; break; } @@ -3512,7 +3504,7 @@ PMI_FEEDBACK: UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); //pdsch_vars - dump_dlsch2(UE,eNB_id,subframe,coded_bits_per_codeword,round); + dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round); //dump_dlsch2(UE,eNB_id_i,coded_bits_per_codeword); write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); @@ -3542,7 +3534,7 @@ PMI_FEEDBACK: } for (int cw=Kmimo-1; cw>=0; cw--) { - UE->dlsch[0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; + UE->dlsch[subframe&0x1][0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; coded_bits_per_codeword = get_G(&eNB->frame_parms, eNB->dlsch[0][cw]->harq_processes[0]->nb_rb, eNB->dlsch[0][cw]->harq_processes[0]->rb_alloc, @@ -3553,7 +3545,7 @@ PMI_FEEDBACK: subframe, (transmission_mode<7?0:transmission_mode)); - UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid]->G = coded_bits_per_codeword; + UE->dlsch[subframe&0x1][0][cw]->harq_processes[UE->dlsch[subframe&0x1][0][cw]->current_harq_pid]->G = coded_bits_per_codeword; @@ -3577,7 +3569,7 @@ PMI_FEEDBACK: start_meas(&UE->dlsch_unscrambling_stats); dlsch_unscrambling(&UE->frame_parms, 0, - UE->dlsch[0][cw], + UE->dlsch[subframe&0x1][0][cw], coded_bits_per_codeword, UE->pdsch_vars[subframe&0x1][eNB_id]->llr[cw], 0, @@ -3588,15 +3580,15 @@ PMI_FEEDBACK: ret = dlsch_decoding(UE, UE->pdsch_vars[subframe&0x1][eNB_id]->llr[cw], &UE->frame_parms, - UE->dlsch[0][cw], - UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid], + UE->dlsch[subframe&0x1][0][cw], + UE->dlsch[subframe&0x1][0][cw]->harq_processes[UE->dlsch[subframe&0x1][0][cw]->current_harq_pid], subframe, - UE->dlsch[0][cw]->current_harq_pid, + UE->dlsch[subframe&0x1][0][cw]->current_harq_pid, 1,llr8_flag); stop_meas(&UE->dlsch_decoding_stats); if (cw==1) { - if (ret <= UE->dlsch[0][cw]->max_turbo_iterations) { + if (ret <= UE->dlsch[subframe&0x1][0][cw]->max_turbo_iterations) { } else { errs2[round]++; } @@ -3604,10 +3596,10 @@ PMI_FEEDBACK: } - stop_meas(&UE->phy_proc_rx); + stop_meas(&UE->phy_proc_rx[subframe&0x1]); - if (ret <= UE->dlsch[0][0]->max_turbo_iterations) { + if (ret <= UE->dlsch[subframe&0x1][0][0]->max_turbo_iterations) { avg_iter += ret; iter_trials++; @@ -3615,15 +3607,15 @@ PMI_FEEDBACK: if (n_frames==1) printf("No DLSCH errors found (round %d),uncoded ber %f\n",round,uncoded_ber); - UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->TBS; + UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->TBS; TB0_active = 0; - if (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC + if (UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC /* - for (round = 0 ; round < UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->round ; round++) { + for (round = 0 ; round < UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->round ; round++) { // re-encoding of first stream - dlsch0_ue_harq = UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]; - dlsch0_eNB_harq = UE->dlsch[eNB_id]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]; + dlsch0_ue_harq = UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]; + dlsch0_eNB_harq = UE->dlsch[subframe&0x1][eNB_id]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]; dlsch0_eNB_harq->mimo_mode = LARGE_CDD; dlsch0_eNB_harq->rb_alloc[0] = dlsch0_ue_harq->rb_alloc_even[0]; dlsch0_eNB_harq->nb_rb = dlsch0_ue_harq->nb_rb; @@ -3635,13 +3627,13 @@ PMI_FEEDBACK: dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off; dlsch0_eNB_harq->status = dlsch0_ue_harq->status; - UE->dlsch[eNB_id]->active = UE->dlsch[eNB_id][0]->active; - UE->dlsch[eNB_id]->rnti = UE->dlsch[eNB_id][0]->rnti; + UE->dlsch[subframe&0x1][eNB_id]->active = UE->dlsch[subframe&0x1][eNB_id][0]->active; + UE->dlsch[subframe&0x1][eNB_id]->rnti = UE->dlsch[subframe&0x1][eNB_id][0]->rnti; - dlsch_encoding(UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->b, + dlsch_encoding(UE->dlsch[subframe&0x1][eNB_id][0]->harq_processes[UE->dlsch[subframe&0x1][eNB_id][0]->current_harq_pid]->b, &UE->frame_parms, num_pdcch_symbols, - UE->dlsch[0], + UE->dlsch[subframe&0x1][0], 0,subframe, &UE->dlsch_rate_matching_stats, &UE->dlsch_turbo_encoding_stats, @@ -3668,18 +3660,18 @@ PMI_FEEDBACK: //if ((n_frames==1) || (SNR>=30)) printf("DLSCH errors found (round %d), uncoded ber %f\n",round,uncoded_ber); - for (s=0; s<UE->dlsch[0][0]->harq_processes[0]->C; s++) { - if (s<UE->dlsch[0][0]->harq_processes[0]->Cminus) - Kr = UE->dlsch[0][0]->harq_processes[0]->Kminus; + for (s=0; s<UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->C; s++) { + if (s<UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Cminus) + Kr = UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kminus; else - Kr = UE->dlsch[0][0]->harq_processes[0]->Kplus; + Kr = UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kplus; Kr_bytes = Kr>>3; printf("Decoded_output (Segment %d):\n",s); for (i=0; i<Kr_bytes; i++) - printf("%d : %x (%x)\n",i,UE->dlsch[0][0]->harq_processes[0]->c[s][i],UE->dlsch[0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]); + printf("%d : %x (%x)\n",i,UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->c[s][i],UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]); } sprintf(fname,"rxsig0_r%d.m",round); @@ -3729,12 +3721,12 @@ PMI_FEEDBACK: } //pdsch_vars - dump_dlsch2(UE,eNB_id,subframe,coded_bits_per_codeword,round); + dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round); /* write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); write_output("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); write_output("dlsch_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4); - write_output("dlsch_w.m","w",UE->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); + write_output("dlsch_w.m","w",UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); */ if (round == 3) exit(-1); @@ -3743,7 +3735,7 @@ PMI_FEEDBACK: // printf("round %d errors %d/%d\n",round,errs[round],trials); round++; - // UE->dlsch[0][0]->harq_processes[0]->round++; + // UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->round++; } if (xforms==1) { @@ -3783,7 +3775,7 @@ PMI_FEEDBACK: double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx = (double)UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; + double t_rx = (double)UE->phy_proc_rx[subframe&0x1].p_time/cpu_freq_GHz/1000.0; double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0; double t_rx_dec = (double)UE->dlsch_decoding_stats.p_time/cpu_freq_GHz/1000.0; @@ -3933,7 +3925,7 @@ PMI_FEEDBACK: rate*effective_rate, 100*effective_rate, rate, - rate*get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs), + rate*get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); @@ -3972,10 +3964,10 @@ PMI_FEEDBACK: eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials); printf("\n\nUE RX function statistics (per 1ms subframe)\n\n"); - std_phy_proc_rx = sqrt((double)UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/UE->phy_proc_rx.trials - pow((double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0, - UE->phy_proc_rx.trials*2/3); + std_phy_proc_rx = sqrt((double)UE->phy_proc_rx[subframe&0x1].diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->phy_proc_rx[subframe&0x1].trials - pow((double)UE->phy_proc_rx[subframe&0x1].diff/UE->phy_proc_rx[subframe&0x1].trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx[subframe&0x1].diff/UE->phy_proc_rx[subframe&0x1].trials/cpu_freq_GHz/1000.0, + UE->phy_proc_rx[subframe&0x1].trials*2/3); printf("|__Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, @@ -4009,7 +4001,7 @@ PMI_FEEDBACK: printf("|__ DLSCH Rate Unmatching :%f us (%d trials)\n", (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials); printf("|__ DLSCH Turbo Decoding(%d bits) :%f us (%d trials)\n", - UE->dlsch[0][0]->harq_processes[0]->Cminus ? UE->dlsch[0][0]->harq_processes[0]->Kminus : UE->dlsch[0][0]->harq_processes[0]->Kplus, + UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Cminus ? UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kminus : UE->dlsch[subframe&0x1][0][0]->harq_processes[0]->Kplus, (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials); printf(" |__ init %f us (cycles/iter %f, %d trials)\n", (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, @@ -4187,7 +4179,7 @@ PMI_FEEDBACK: eNB->dlsch_modulation_stats.trials, eNB->dlsch_scrambling_stats.trials, eNB->dlsch_encoding_stats.trials, - UE->phy_proc_rx.trials, + UE->phy_proc_rx[subframe&0x1].trials, UE->ofdm_demod_stats.trials, UE->dlsch_rx_pdcch_stats.trials, UE->dlsch_llr_stats.trials, @@ -4200,7 +4192,7 @@ PMI_FEEDBACK: get_time_meas_us(&eNB->dlsch_modulation_stats), get_time_meas_us(&eNB->dlsch_scrambling_stats), get_time_meas_us(&eNB->dlsch_encoding_stats), - get_time_meas_us(&UE->phy_proc_rx), + get_time_meas_us(&UE->phy_proc_rx[subframe&0x1]), nsymb*get_time_meas_us(&UE->ofdm_demod_stats), get_time_meas_us(&UE->dlsch_rx_pdcch_stats), 3*get_time_meas_us(&UE->dlsch_llr_stats), @@ -4240,7 +4232,7 @@ PMI_FEEDBACK: eNB->dlsch_modulation_stats.trials, eNB->dlsch_scrambling_stats.trials, eNB->dlsch_encoding_stats.trials, - UE->phy_proc_rx.trials, + UE->phy_proc_rx[subframe&0x1].trials, UE->ofdm_demod_stats.trials, UE->dlsch_rx_pdcch_stats.trials, UE->dlsch_llr_stats.trials, @@ -4298,7 +4290,7 @@ PMI_FEEDBACK: printf("eNB %d\n",i); free_eNB_dlsch(eNB->dlsch[0][i]); printf("UE %d\n",i); - free_ue_dlsch(UE->dlsch[0][i]); + free_ue_dlsch(UE->dlsch[subframe&0x1][0][i]); } diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index fb2fa506ac20f01aedc334f9283ca4836f75b895..69de4aee9f000337292bff2f6d5c2e5b9f9d3822 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -50,6 +50,7 @@ PHY_VARS_eNB *eNB; PHY_VARS_UE *UE; +double cpuf; DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_1E[2]; #define UL_RB_ALLOC 0x1ff; @@ -118,6 +119,8 @@ int main(int argc, char **argv) #endif */ + cpuf = get_cpu_freq_GHz(); + logInit(); number_of_cards = 1; diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c index 806a206a2bd851800126a929b7a9f51bfa14dec9..f117879d6b49fd43f390d3c9999dae237bc3a492 100644 --- a/openair1/SIMULATION/LTE_PHY/pbchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c @@ -50,6 +50,8 @@ PHY_VARS_eNB *eNB,*eNB1,*eNB2; PHY_VARS_UE *UE; +double cpuf; + #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 int32_t *dummybuf[4]; @@ -116,6 +118,8 @@ int main(int argc, char **argv) char title[255]; #endif + cpuf = get_cpu_freq_GHz(); + logInit(); number_of_cards = 1; diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index 1ba79bdb0a4182ff10a2c5ae3609025310704381..2b13449c6172498a3ee2c07fd49ec41e2fb9b7e5 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -50,6 +50,7 @@ PHY_VARS_UE *UE; #define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2) #define DLSCH_RB_ALLOC ((uint16_t)0x1fbf) // igore DC component,RB13 +double cpuf; DCI_PDU DCI_pdu; @@ -457,6 +458,8 @@ int main(int argc, char **argv) number_of_cards = 1; + cpuf = get_cpu_freq_GHz(); + logInit(); @@ -650,6 +653,7 @@ int main(int argc, char **argv) printf("-h This message\n"); printf("-a Use AWGN channel and not multipath\n"); printf("-c TDD config\n"); + printf("-S Subframe number (0..9)\n"); printf("-R N_RB_DL\n"); printf("-F use FDD frame\n"); printf("-p Use extended prefix mode\n"); @@ -1085,12 +1089,10 @@ int main(int argc, char **argv) // write_output("H00.m","h00",&(UE->common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); // do PDCCH procedures here - UE->pdcch_vars[0]->crnti = n_rnti; + UE->pdcch_vars[0][0]->crnti = n_rnti; // printf("Doing RX : num_pdcch_symbols at TX %d\n",num_pdcch_symbols); - rx_pdcch(&UE->common_vars, - UE->pdcch_vars, - &UE->frame_parms, + rx_pdcch(UE, trial, subframe, 0, @@ -1118,7 +1120,7 @@ int main(int argc, char **argv) dl_rx=0; if (n_frames==1) { - numCCE = get_nCCE(UE->pdcch_vars[0]->num_pdcch_symbols, &UE->frame_parms, get_mi(&UE->frame_parms,subframe)); + numCCE = get_nCCE(UE->pdcch_vars[0][0]->num_pdcch_symbols, &UE->frame_parms, get_mi(&UE->frame_parms,subframe)); for (i = 0; i < dci_cnt; i++) printf("dci %d: rnti 0x%x, format %d, L %d, nCCE %d/%d dci_length %d\n",i, dci_alloc_rx[i].rnti, dci_alloc_rx[i].format, @@ -1167,7 +1169,7 @@ int main(int argc, char **argv) // exit(-1); } - if (UE->pdcch_vars[0]->num_pdcch_symbols != num_pdcch_symbols) + if (UE->pdcch_vars[0][0]->num_pdcch_symbols != num_pdcch_symbols) n_errors_cfi++; /* @@ -1224,9 +1226,9 @@ int main(int argc, char **argv) if (n_tx==2) write_output("H10.m","h10",&(UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); - write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",UE->pdcch_vars[eNb_id]->rxdataF_ext[0],3*12*UE->frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNb_id]->rxdataF_comp[0],4*12*UE->frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNb_id]->llr,2400,1,4); + write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",UE->pdcch_vars[0][eNb_id]->rxdataF_ext[0],3*12*UE->frame_parms.N_RB_DL,1,1); + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[0][eNb_id]->rxdataF_comp[0],4*12*UE->frame_parms.N_RB_DL,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[0][eNb_id]->llr,2400,1,4); } lte_sync_time_free(); diff --git a/openair1/SIMULATION/LTE_PHY/prachsim.c b/openair1/SIMULATION/LTE_PHY/prachsim.c index 7acc07528c4763cc3e23fb4d34bece13be8c7473..52339cdc5d585c1a20f6276bc680283d6bb46afa 100644 --- a/openair1/SIMULATION/LTE_PHY/prachsim.c +++ b/openair1/SIMULATION/LTE_PHY/prachsim.c @@ -45,7 +45,7 @@ PHY_VARS_UE *UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 - +double cpuf; extern uint16_t prach_root_sequence_map0_3[838]; @@ -99,6 +99,8 @@ int main(int argc, char **argv) int NCS_config = 1,rootSequenceIndex=0; int threequarter_fs = 0; + cpuf = get_cpu_freq_GHz(); + logInit(); number_of_cards = 1; diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index 77bfcb18cf68682f2d80f87cd371c92c5e45d25d..3869851f712d875c09f6c8bbd82db821eda52fb7 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -47,7 +47,7 @@ PHY_VARS_UE *UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 - +double cpuf; int main(int argc, char **argv) { @@ -85,11 +85,13 @@ int main(int argc, char **argv) // double pucch_sinr; uint8_t osf=1,N_RB_DL=25; - uint32_t pucch_tx=0,pucch1_missed=0,pucch1_false=0,sig; + uint32_t pucch_tx=0,pucch1_missed=0,pucch1_false=0,pucch3_false=0,sig; PUCCH_FMT_t pucch_format = pucch_format1; PUCCH_CONFIG_DEDICATED pucch_config_dedicated; uint8_t subframe=0; uint8_t pucch_payload,pucch_payload_rx; + uint8_t pucch3_payload_size=7; + uint8_t pucch3_payload[21],pucch3_payload_rx[21]; double tx_gain=1.0; int32_t stat; double stat_no_sig,stat_sig; @@ -98,9 +100,14 @@ int main(int argc, char **argv) uint16_t n1_pucch = 0; uint16_t n2_pucch = 0; + uint16_t n3_pucch = 20; + + uint16_t n_rnti=0x1234; number_of_cards = 1; + cpuf = get_cpu_freq_GHz(); + while ((c = getopt (argc, argv, "har:pf:g:n:s:S:x:y:z:N:F:T:R:")) != -1) { switch (c) { case 'a': @@ -116,6 +123,8 @@ int main(int argc, char **argv) pucch_format = pucch_format1a; else if (atoi(optarg)==2) pucch_format = pucch_format1b; + else if (atoi(optarg)==6) // 3,4,5 is reserved for format2,2a,2b + pucch_format = pucch_format3; else { printf("Unsupported pucch_format %d\n",atoi(optarg)); exit(-1); @@ -280,7 +289,7 @@ int main(int argc, char **argv) printf("-N Noise variance in dB\n"); printf("-R N_RB_DL\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); - printf("-f PUCCH format (0=1,1=1a,2=1b), formats 2/2a/2b not supported\n"); + printf("-f PUCCH format (0=1,1=1a,2=1b,6=3), formats 2/2a/2b not supported\n"); printf("-F Input filename (.txt format) for RX conformance testing\n"); exit (-1); break; @@ -360,18 +369,34 @@ int main(int argc, char **argv) UE->frame_parms.pucch_config_common.nRB_CQI = 4; UE->frame_parms.pucch_config_common.nCS_AN = 6; - pucch_payload = 0; - - generate_pucch1x(UE->common_vars.txdataF, - frame_parms, - UE->ncs_cell, - pucch_format, - &pucch_config_dedicated, - n1_pucch, - 0, //shortened_format, - &pucch_payload, - AMP, //amp, - subframe); //subframe + + if( (pucch_format == pucch_format1) || (pucch_format == pucch_format1a) || (pucch_format == pucch_format1b) ){ + pucch_payload = 0; + generate_pucch1x(UE->common_vars.txdataF, + frame_parms, + UE->ncs_cell, + pucch_format, + &pucch_config_dedicated, + n1_pucch, + 0, //shortened_format, + &pucch_payload, + AMP, //amp, + subframe); //subframe + }else if( pucch_format == pucch_format3){ + for(i=0;i<pucch3_payload_size;i++) + pucch3_payload[i]=(uint8_t)(taus()&0x1); + generate_pucch3x(UE->common_vars.txdataF, + frame_parms, + UE->ncs_cell, + pucch_format, + &pucch_config_dedicated, + n3_pucch, + 0, //shortened_format, + pucch3_payload, + AMP, //amp, + subframe, //subframe + n_rnti); //rnti + } write_output("txsigF0.m","txsF0", &UE->common_vars.txdataF[0][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*nsymb,1,1); tx_lev = 0; @@ -427,6 +452,7 @@ int main(int argc, char **argv) pucch_tx = 0; pucch1_missed=0; pucch1_false=0; + pucch3_false=0; stat_no_sig = 0; stat_sig = 0; @@ -538,7 +564,7 @@ int main(int argc, char **argv) n1_pucch, n2_pucch, 0, //shortened_format, - &pucch_payload_rx, //payload, + (pucch_format==pucch_format3) ? pucch3_payload_rx : &pucch_payload_rx, //payload, 0 /* frame not defined, let's pass 0 */, subframe, pucch1_thres); @@ -559,8 +585,15 @@ int main(int argc, char **argv) printf("EXIT\n"); exit(-1); }*/ - } else { + } else if( (pucch_format==pucch_format1a) || (pucch_format==pucch_format1b) ) { pucch1_false = (pucch_payload_rx != pucch_payload) ? (pucch1_false+1) : pucch1_false; + } else if (pucch_format==pucch_format3){ + for(i=0;i<pucch3_payload_size;i++){ + if(pucch3_payload[i]!=pucch3_payload_rx[i]){ + pucch3_false = (pucch3_false+1); + break; + } + } } // printf("sig %d\n",sig); @@ -574,7 +607,8 @@ int main(int argc, char **argv) printf("pucch_trials %d : pucch1a_errors %d\n",pucch_tx,pucch1_false); else if (pucch_format==pucch_format1b) printf("pucch_trials %d : pucch1b_errors %d\n",pucch_tx,pucch1_false); - + else if (pucch_format==pucch_format3) + printf("pucch_trials %d : pucch3_errors %d\n",pucch_tx,pucch3_false); } if (n_frames==1) { diff --git a/openair1/SIMULATION/LTE_PHY/syncsim.c b/openair1/SIMULATION/LTE_PHY/syncsim.c index 6e74f7bc01f2181a09c44dbddf5c522b43a0c710..97a94a1a4323f3bda14401c39425b1c761b6db3b 100644 --- a/openair1/SIMULATION/LTE_PHY/syncsim.c +++ b/openair1/SIMULATION/LTE_PHY/syncsim.c @@ -406,7 +406,7 @@ int main(int argc, char **argv) DCI_ALLOC_t dci_alloc[8],dci_alloc_rx[8]; uint16_t n_rnti=1234,dci_cnt; - uint16_t coded_bits_per_codeword; + unsigned int coded_bits_per_codeword; double tmp_re,tmp_im,foff,deltaF=0.0,cs,sn; uint32_t carrier_freq[4]= {1907600000,1907600000,1907600000,1907600000}; uint32_t rf_mode[4] = {55759,55759,55759,55759}; @@ -1739,7 +1739,7 @@ int main(int argc, char **argv) PHY_vars_UE[0]->lte_ue_pdcch_vars[0]->num_pdcch_symbols, 0); - dump_dlsch2(PHY_vars_UE[0],0,0,coded_bits_per_codeword); + dump_dlsch2(PHY_vars_UE[0],0,0,&coded_bits_per_codeword); } } else { diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 55c6b8387eef3df727539536679b6d4a6a8fa00a..dbce85851695fb10b49f1a655221806ac2b93a02 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -42,6 +42,7 @@ #include "SCHED/vars.h" #include "LAYER2/MAC/vars.h" #include "OCG_vars.h" +#include "intertask_interface_init.h" #include "unitary_defs.h" @@ -50,6 +51,7 @@ PHY_VARS_eNB *eNB; PHY_VARS_UE *UE; +double cpuf; @@ -162,8 +164,8 @@ void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mc } -extern void eNB_fep_full(PHY_VARS_eNB *eNB); -extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB); +extern void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc); +extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc); int main(int argc, char **argv) { @@ -195,7 +197,7 @@ int main(int argc, char **argv) int chMod = 0 ; int UE_id = 0; unsigned char nb_rb=25,first_rb=0,mcs=0,round=0,bundling_flag=1; - unsigned char l; + //unsigned char l; unsigned char awgn_flag = 0 ; SCM_t channel_model=Rice1; @@ -244,14 +246,14 @@ int main(int argc, char **argv) int hold_channel=0; channel_desc_t *UE2eNB; - uint8_t control_only_flag = 0; + //uint8_t control_only_flag = 0; int delay = 0; double maxDoppler = 0.0; uint8_t srs_flag = 0; uint8_t N_RB_DL=25,osf=1; - uint8_t cyclic_shift = 0; + //uint8_t cyclic_shift = 0; uint8_t cooperation_flag = 0; //0 no cooperation, 1 delay diversity, 2 Alamouti uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; uint8_t tdd_config=3,frame_type=FDD; @@ -273,6 +275,7 @@ int main(int argc, char **argv) uint8_t max_turbo_iterations=4; uint8_t parallel_flag=0; int nb_rb_set = 0; + int sf; int threequarter_fs=0; int ndi; @@ -280,11 +283,19 @@ int main(int argc, char **argv) opp_enabled=1; // to enable the time meas cpu_freq_GHz = (double)get_cpu_freq_GHz(); + cpuf = cpu_freq_GHz; printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz); - logInit(); + /* + // enable these lines if you need debug info + // however itti will catch all signals, so ctrl-c won't work anymore + // alternatively you can disable ITTI completely in CMakeLists.txt + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); + set_comp_log(PHY,LOG_DEBUG,LOG_MED,1); + set_glog(LOG_DEBUG,LOG_MED); + */ while ((c = getopt (argc, argv, "hapZEbm:n:Y:X:x:s:w:e:q:d:D:O:c:r:i:f:y:c:oA:C:R:g:N:l:S:T:QB:PI:LF")) != -1) { switch (c) { @@ -452,9 +463,9 @@ int main(int argc, char **argv) first_rb = atoi(optarg); break; - case 'c': - cyclic_shift = atoi(optarg); - break; + //case 'c': + // cyclic_shift = atoi(optarg); + // break; case 'E': threequarter_fs=1; @@ -546,7 +557,9 @@ int main(int argc, char **argv) case 'h': default: - printf("%s -h(elp) -a(wgn on) -m mcs -n n_frames -s snr0 -t delay_spread -p (extended prefix on) -r nb_rb -f first_rb -c cyclic_shift -o (srs on) -g channel_model [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M'), -d Channel delay, -D maximum Doppler shift \n", + /* option "-c cyclic_shift" is not used, let's remove from documentation */ + //printf("%s -h(elp) -a(wgn on) -m mcs -n n_frames -s snr0 -t delay_spread -p (extended prefix on) -r nb_rb -f first_rb -c cyclic_shift -o (srs on) -g channel_model [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M'), -d Channel delay, -D maximum Doppler shift \n", + printf("%s -h(elp) -a(wgn on) -m mcs -n n_frames -s snr0 -t delay_spread -p (extended prefix on) -r nb_rb -f first_rb -o (srs on) -g channel_model [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M'), -d Channel delay, -D maximum Doppler shift \n", argv[0]); exit(1); break; @@ -566,6 +579,11 @@ int main(int argc, char **argv) osf, 0); + // for a call to phy_reset_ue later we need PHY_vars_UE_g allocated and pointing to UE + PHY_vars_UE_g = (PHY_VARS_UE***)malloc(sizeof(PHY_VARS_UE**)); + PHY_vars_UE_g[0] = (PHY_VARS_UE**) malloc(sizeof(PHY_VARS_UE*)); + PHY_vars_UE_g[0][0] = UE; + if (nb_rb_set == 0) nb_rb = eNB->frame_parms.N_RB_UL; @@ -580,8 +598,6 @@ int main(int argc, char **argv) txdata = UE->common_vars.txdata; - - nsymb = (eNB->frame_parms.Ncp == NORMAL) ? 14 : 12; @@ -630,23 +646,31 @@ int main(int argc, char **argv) fl_show_form (form_enb->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); } - UE->pdcch_vars[0]->crnti = 14; + UE->pdcch_vars[0][0]->crnti = 14; + UE->frame_parms.soundingrs_ul_config_common.enabled_flag = srs_flag; UE->frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig = 2; - UE->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 7; + UE->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 3; + UE->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = srs_flag; + UE->soundingrs_ul_config_dedicated[eNB_id].duration = 1; + UE->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex = 2; UE->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth = 0; UE->soundingrs_ul_config_dedicated[eNB_id].transmissionComb = 0; UE->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition = 0; + UE->soundingrs_ul_config_dedicated[eNB_id].cyclicShift = 0; + eNB->frame_parms.soundingrs_ul_config_common.enabled_flag = srs_flag; eNB->frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig = 2; - eNB->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 7; - - eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex = 1; + eNB->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 3; + eNB->soundingrs_ul_config_dedicated[UE_id].srsConfigDedicatedSetup = srs_flag; + eNB->soundingrs_ul_config_dedicated[UE_id].duration = 1; + eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex = 2; eNB->soundingrs_ul_config_dedicated[UE_id].srs_Bandwidth = 0; eNB->soundingrs_ul_config_dedicated[UE_id].transmissionComb = 0; eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition = 0; + eNB->soundingrs_ul_config_dedicated[UE_id].cyclicShift = 0; + eNB->cooperation_flag = cooperation_flag; - // eNB->eNB_UE_stats[0].SRS_parameters = UE->SRS_parameters; eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = beta_ACK; eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index = beta_RI; @@ -657,6 +681,11 @@ int main(int argc, char **argv) UE->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled = 1; + // disable periodic cqi/ri reporting + UE->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1; + UE->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1; + + printf("PUSCH Beta : ACK %f, RI %f, CQI %f\n",(double)beta_ack[beta_ACK]/8,(double)beta_ri[beta_RI]/8,(double)beta_cqi[beta_CQI]/8); UE2eNB = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, @@ -675,31 +704,38 @@ int main(int argc, char **argv) UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); if (parallel_flag == 1) { + extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); + extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *); init_fep_thread(eNB,NULL); init_td_thread(eNB,NULL); } // Create transport channel structures for 2 transport blocks (MIMO) for (i=0; i<2; i++) { eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0,&eNB->frame_parms); - UE->dlsch[0][i] = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); - if (!eNB->dlsch[0][i]) { printf("Can't get eNB dlsch structures\n"); exit(-1); } - - if (!UE->dlsch[0][i]) { - printf("Can't get ue dlsch structures\n"); - exit(-1); - } - eNB->dlsch[0][i]->rnti = 14; - UE->dlsch[0][i]->rnti = 14; - - } - - + } + /* allocate memory for both subframes (only one is really used + * but there is now "copy_harq_proc_struct" which needs both + * to be valid) + * TODO: refine this somehow (necessary?) + */ + for (sf = 0; sf < 2; sf++) { + for (i=0; i<2; i++) { + UE->dlsch[sf][0][i] = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); + if (!UE->dlsch[sf][0][i]) { + printf("Can't get ue dlsch structures\n"); + exit(-1); + } + UE->dlsch[sf][0][i]->rnti = 14; + } + } + UE->dlsch_SI[0] = new_ue_dlsch(1,1,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->dlsch_ra[0] = new_ue_dlsch(1,1,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); UE->measurements.rank[0] = 0; UE->transmission_mode[0] = 2; @@ -735,7 +771,7 @@ int main(int argc, char **argv) init_ul_hopping(&eNB->frame_parms); - UE->dlsch[0][0]->harq_ack[ul_subframe2pdcch_alloc_subframe(&eNB->frame_parms,subframe)].send_harq_status = 1; + UE->dlsch[subframe&1][0][0]->harq_ack[ul_subframe2pdcch_alloc_subframe(&eNB->frame_parms,subframe)].send_harq_status = 1; UE->ulsch_Msg3_active[eNB_id] = 0; UE->ul_power_control_dedicated[eNB_id].accumulationEnabled=1; @@ -841,6 +877,7 @@ int main(int argc, char **argv) while (!feof(input_fdUL)) { ret=fscanf(input_fdUL,"%s %s",input_val_str,input_val_str2);//&input_val1,&input_val2); + if (ret != 2) printf("ERROR: error reading file\n"); if ((i%4)==0) { ((short*)txdata[0])[i/2] = (short)((1<<15)*strtod(input_val_str,NULL)); @@ -915,6 +952,10 @@ int main(int argc, char **argv) initialize(&time_vector_rx_dec); ndi=0; + + phy_reset_ue(0,0,0); + UE->UE_mode[eNB_id]=PUSCH; + for (trials = 0; trials<n_frames; trials++) { // printf("*"); // UE->frame++; diff --git a/openair1/SIMULATION/TOOLS/abstraction.c b/openair1/SIMULATION/TOOLS/abstraction.c index 8fce4d25a62cfbd1818765c4082a2b172892ed90..88b3ce6406bfbf72272d75f155f69edefb1704b4 100644 --- a/openair1/SIMULATION/TOOLS/abstraction.c +++ b/openair1/SIMULATION/TOOLS/abstraction.c @@ -115,7 +115,7 @@ int freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) start_meas(&desc->interp_freq); - for (f=-n_samples_max/2,f2=-n_samples/2; f<=n_samples_max/2; f+=d,f2++) { + for (f=-n_samples_max/2,f2=-n_samples/2; f<n_samples_max/2; f+=d,f2++) { clut = cos_lut[n_samples_max/2+f]; slut = sin_lut[n_samples_max/2+f]; @@ -318,3 +318,4 @@ double pbch_bler(double sinr) return(bler); } + diff --git a/openair1/SIMULATION/TOOLS/defs.h b/openair1/SIMULATION/TOOLS/defs.h index 336187ff1c9e6310d20d6bb1fc85562ec637b971..4378ca2da309c1002a7e99408dbbd74ac4a74519 100644 --- a/openair1/SIMULATION/TOOLS/defs.h +++ b/openair1/SIMULATION/TOOLS/defs.h @@ -169,7 +169,16 @@ typedef enum { Rice1, Rice1_corr, Rice1_anticorr, - AWGN + AWGN, + Rayleigh1_orthogonal, + Rayleigh1_orth_eff_ch_TM4_prec_real, + Rayleigh1_orth_eff_ch_TM4_prec_imag, + Rayleigh8_orth_eff_ch_TM4_prec_real, + Rayleigh8_orth_eff_ch_TM4_prec_imag, + TS_SHIFT, + EPA_low, + EPA_medium, + EPA_high, } SCM_t; /** diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 6e034332c0fcefe287cd9180ac2dfc3f0abe8cc5..98988ea4cb88097ae89d4b64586e610c8bf7e205 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -32,6 +32,8 @@ #include "UTIL/LOG/log.h" //#define DEBUG_CH +extern void print_shorts(char *s,__m128i *x); + void fill_channel_desc(channel_desc_t *chan_desc, uint8_t nb_tx, uint8_t nb_rx, @@ -42,7 +44,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, struct complex** R_sqrt, double Td, double sampling_rate, - double channel_bandwidth, + double channel_bandwidth, double ricean_factor, double aoa, double forgetting_factor, @@ -52,11 +54,12 @@ void fill_channel_desc(channel_desc_t *chan_desc, uint8_t random_aoa) { + uint16_t i,j; double delta_tau; LOG_I(OCM,"[CHANNEL] Getting new channel descriptor, nb_tx %d, nb_rx %d, nb_taps %d, channel_length %d\n", - nb_tx,nb_rx,nb_taps,channel_length); + nb_tx,nb_rx,nb_taps,channel_length); chan_desc->nb_tx = nb_tx; chan_desc->nb_rx = nb_rx; @@ -64,31 +67,29 @@ void fill_channel_desc(channel_desc_t *chan_desc, chan_desc->channel_length = channel_length; chan_desc->amps = amps; LOG_D(OCM,"[CHANNEL] Doing delays ...\n"); - if (delays==NULL) { chan_desc->delays = (double*) malloc(nb_taps*sizeof(double)); delta_tau = Td/nb_taps; - for (i=0; i<nb_taps; i++) chan_desc->delays[i] = ((double)i)*delta_tau; - } else - chan_desc->delays = delays; - - chan_desc->Td = Td; - chan_desc->sampling_rate = sampling_rate; - chan_desc->channel_bandwidth = channel_bandwidth; - chan_desc->ricean_factor = ricean_factor; - chan_desc->aoa = aoa; - chan_desc->random_aoa = random_aoa; - chan_desc->forgetting_factor = forgetting_factor; - chan_desc->channel_offset = channel_offset; - chan_desc->path_loss_dB = path_loss_dB; - chan_desc->first_run = 1; - chan_desc->ip = 0.0; - chan_desc->max_Doppler = max_Doppler; - chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); - chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); - chan_desc->a = (struct complex**) malloc(nb_taps*sizeof(struct complex*)); + } + else + chan_desc->delays = delays; + chan_desc->Td = Td; + chan_desc->sampling_rate = sampling_rate; + chan_desc->channel_bandwidth = channel_bandwidth; + chan_desc->ricean_factor = ricean_factor; + chan_desc->aoa = aoa; + chan_desc->random_aoa = random_aoa; + chan_desc->forgetting_factor = forgetting_factor; + chan_desc->channel_offset = channel_offset; + chan_desc->path_loss_dB = path_loss_dB; + chan_desc->first_run = 1; + chan_desc->ip = 0.0; + chan_desc->max_Doppler = max_Doppler; + chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->a = (struct complex**) malloc(nb_taps*sizeof(struct complex*)); LOG_D(OCM,"[CHANNEL] Filling ch \n"); @@ -99,27 +100,30 @@ void fill_channel_desc(channel_desc_t *chan_desc, chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); // allocate for up to 100 RBs, 12 samples per RB LOG_D(OCM,"[CHANNEL] Filling a (nb_taps %d)\n",nb_taps); - for (i = 0; i<nb_taps; i++) { - LOG_D(OCM,"tap %d (%p,%d)\n",i,&chan_desc->a[i],nb_tx*nb_rx * sizeof(struct complex)); + LOG_D(OCM,"tap %d (%p,%zu)\n",i,&chan_desc->a[i],nb_tx*nb_rx * sizeof(struct complex)); chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); } LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n"); - if (R_sqrt == NULL) { - chan_desc->R_sqrt = (struct complex**) calloc(nb_taps,sizeof(struct complex*)); - + chan_desc->R_sqrt = (struct complex**) calloc(nb_taps,sizeof(struct complex*)); for (i = 0; i<nb_taps; i++) { - chan_desc->R_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); - + chan_desc->R_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } } - } else { - chan_desc->R_sqrt = R_sqrt; + } + else { + chan_desc->R_sqrt = (struct complex**) calloc(nb_taps,sizeof(struct complex*)); + for (i = 0; i<nb_taps; i++) { + //chan_desc->R_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); + //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; + /* all chan_desc share the same R_sqrt, coming from caller */ + chan_desc->R_sqrt[i] = R_sqrt[0]; + } } for (i = 0; i<nb_taps; i++) { @@ -129,8 +133,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, } LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor); - - for (i=0; i<chan_desc->nb_taps; i++) + for (i=0;i<chan_desc->nb_taps;i++) LOG_D(OCM,"[CHANNEL] tap %d: amp %f, delay %f\n",i,chan_desc->amps[i],chan_desc->delays[i]); chan_desc->nb_paths=10; @@ -160,12 +163,14 @@ double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; double default_amps_lin[] = {0.3868472 , 0.3094778 , 0.1547389 , 0.0773694 , 0.0386847 , 0.0193424 , 0.0096712 , 0.0038685}; double default_amp_lin[] = {1}; +double ts_shift_delays[] = {0, 1/7.68}; +double ts_shift_amps[] = {0, 1}; + //correlation matrix for a 2x2 channel with full Tx correlation struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, - {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, - {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, - {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0} -}; + {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, + {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, + {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}}; struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; //correlation matrix for a fully correlated 2x1 channel (h1==h2) @@ -174,10 +179,9 @@ struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; //correlation matrix for a 2x2 channel with full Tx anti-correlation struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, - {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, - {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, - {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0} -}; + {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, + {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, + {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}}; struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) @@ -186,12 +190,62 @@ struct complex *R_sqrt_21_anticorr[1] = {R_sqrt_21_anticorr_tap}; struct complex **R_sqrt_ptr2; +// full correlation matrix in vectorized form for 2x2 channel, where h1 is perfectly orthogonal to h2 + +struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, + {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, + {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, + {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0}}; +struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; + +// full correlation matrix for TM4 to make orthogonal effective channel + + + + +struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, + {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {-0.70711,0.0}, + {0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, + {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}}; +struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap}; + + + + +struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, + {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0,0.70711}, + {0.0,-0.70711}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, + {0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {-0.70711,0.0}}; +struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap}; + +//Correlation matrix for EPA channel +struct complex R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, + {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, + {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, + {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}}; +struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; + +struct complex R_sqrt_22_EPA_high_tap[16] = {{0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, + {0.4500,0.0}, {0.7179,0.0}, {0.2821,0.0}, {0.4500,0.0}, + {0.4500,0.0}, {0.2821,0.0}, {0.7179,0.0}, {0.4500,0.0}, + {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0}}; +struct complex *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap}; + +struct complex R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, + {0.5249,0.0}, {0.8375,0.0}, {0.0806,0.0}, {0.1286,0.0}, + {0.1286,0.0}, {0.0806,0.0}, {0.8375,0.0}, {0.5249,0.0}, + {0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0}}; +struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap}; + + + +//Rayleigh1_orth_eff_ch_TM4 channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, uint8_t nb_rx, SCM_t channel_model, double sampling_rate, - double channel_bandwidth, + double channel_bandwidth, double forgetting_factor, int32_t channel_offset, double path_loss_dB) @@ -203,15 +257,15 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, double aoa,ricean_factor,Td,maxDoppler; int channel_length,nb_taps; - chan_desc->nb_tx = nb_tx; - chan_desc->nb_rx = nb_rx; - chan_desc->sampling_rate = sampling_rate; - chan_desc->channel_bandwidth = channel_bandwidth; - chan_desc->forgetting_factor = forgetting_factor; - chan_desc->channel_offset = channel_offset; - chan_desc->path_loss_dB = path_loss_dB; - chan_desc->first_run = 1; - chan_desc->ip = 0.0; + chan_desc->nb_tx = nb_tx; + chan_desc->nb_rx = nb_rx; + chan_desc->sampling_rate = sampling_rate; + chan_desc->channel_bandwidth = channel_bandwidth; + chan_desc->forgetting_factor = forgetting_factor; + chan_desc->channel_offset = channel_offset; + chan_desc->path_loss_dB = path_loss_dB; + chan_desc->first_run = 1; + chan_desc->ip = 0.0; LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model); @@ -220,27 +274,22 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, LOG_W(OCM,"channel model not yet supported\n"); free(chan_desc); return(NULL); - case SCM_B: LOG_W(OCM,"channel model not yet supported\n"); free(chan_desc); return(NULL); - case SCM_C: chan_desc->nb_taps = 18; chan_desc->Td = 4.625; chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; } - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->amps[i] /= sum_amps; - chan_desc->delays = scm_c_delays; chan_desc->ricean_factor = 1; chan_desc->aoa = 0; @@ -248,42 +297,37 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - if (nb_tx==2 && nb_rx==2) { for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } else if (nb_tx==2 && nb_rx==1) { + } + else if (nb_tx==2 && nb_rx==1) { for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; - } else if (nb_tx==1 && nb_rx==2) { + } + else if (nb_tx==1 && nb_rx==2) { for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; - } else { + } + else { for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } - LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); } } - break; - case SCM_D: LOG_W(OCM,"This is not the real SCM-D model! It is just SCM-C with an additional Rice factor!\n"); chan_desc->nb_taps = 18; @@ -291,15 +335,12 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; } - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->amps[i] /= sum_amps; - chan_desc->delays = scm_c_delays; chan_desc->ricean_factor = 0.1; chan_desc->aoa = 0; @@ -307,57 +348,49 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - if (nb_tx==2 && nb_rx==2) { for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } else if (nb_tx==2 && nb_rx==1) { + } + else if (nb_tx==2 && nb_rx==1) { for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; - } else if (nb_tx==1 && nb_rx==2) { + } + else if (nb_tx==1 && nb_rx==2) { for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; - } else { + } + else { for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } - LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); } } - break; - case EPA: chan_desc->nb_taps = 7; chan_desc->Td = .410; chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; } - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->amps[i] /= sum_amps; - chan_desc->delays = epa_delays; chan_desc->ricean_factor = 1; chan_desc->aoa = 0; @@ -365,53 +398,175 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } else { + } + else { chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } - LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } } - break; - + case EPA_low: + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; + } + else { + printf("Correlation matrices are implemented for 2 x 2 only"); + } + /*else { + chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); + } + }*/ + break; + case EPA_high: + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; + } + else { + printf("Correlation matrices are implemented for 2 x 2 only"); + } + /*else { + chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); + } + }*/ + break; + case EPA_medium: + chan_desc->nb_taps = 7; + chan_desc->Td = .410; + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + sum_amps = 0; + chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); + for (i = 0; i<chan_desc->nb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->amps[i] /= sum_amps; + chan_desc->delays = epa_delays; + chan_desc->ricean_factor = 1; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); + chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); + for (i = 0; i<nb_tx*nb_rx; i++) + chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); + if (nb_tx==2 && nb_rx==2) { + chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); + for (i = 0; i<chan_desc->nb_taps; i++) + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; + } else { + printf("Correlation matrices are implemented for 2 x 2 only"); + } + /*else { + chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { + chan_desc->R_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); + } + }*/ + break; case EVA: chan_desc->nb_taps = 9; chan_desc->Td = 2.51; chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); sum_amps += chan_desc->amps[i]; } - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->amps[i] /= sum_amps; - chan_desc->delays = eva_delays; chan_desc->ricean_factor = 1; chan_desc->aoa = 0; @@ -419,53 +574,41 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } else { + } + else { chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } - LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } } - break; - case ETU: chan_desc->nb_taps = 9; chan_desc->Td = 5.0; chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); sum_amps += chan_desc->amps[i]; } - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->amps[i] /= sum_amps; - chan_desc->delays = etu_delays; chan_desc->ricean_factor = 1; chan_desc->aoa = 0; @@ -473,53 +616,41 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); - if (nb_tx==2 && nb_rx==2) { chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; - } else { + } + else { chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); - for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } - LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } } - break; - case MBSFN: chan_desc->nb_taps = 18; chan_desc->Td = 28.58; chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); - for (i = 0; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); sum_amps += chan_desc->amps[i]; } - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->amps[i] /= sum_amps; - chan_desc->delays = mbsfn_delays; chan_desc->ricean_factor = 1; chan_desc->aoa = 0; @@ -527,341 +658,543 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->chF = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex*)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); - for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); - for (i = 0; i<chan_desc->nb_taps; i++) chan_desc->a[i] = (struct complex*) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex*)); - for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; } - LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } - break; - case Rayleigh8: - nb_taps = 8; - Td = 0.8; - channel_length = (int)11+2*sampling_rate*Td; - ricean_factor = 1; - aoa = .03; - maxDoppler = 0; - - fill_channel_desc(chan_desc, - nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amps_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - break; + + nb_taps = 8; + Td = 0.8; + channel_length = (int)11+2*sampling_rate*Td; + ricean_factor = 1; + aoa = .03; + maxDoppler = 0; + + fill_channel_desc(chan_desc, + nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amps_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; case Rice8: - nb_taps = 8; - Td = 0.8; - channel_length = (int)11+2*sampling_rate*Td; - ricean_factor = 0.1; - aoa = .03; - maxDoppler = 0; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amps_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); - break; + nb_taps = 8; + Td = 0.8; + channel_length = (int)11+2*sampling_rate*Td; + ricean_factor = 0.1; + aoa = 0.7854; + maxDoppler = 0; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amps_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); + break; case Rayleigh1: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 1; - aoa = .03; - maxDoppler = 0; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = .03; + maxDoppler = 0; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; case Rayleigh1_800: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 1; - aoa = .03; - maxDoppler = 800; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = .03; + maxDoppler = 800; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; case Rayleigh1_corr: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 1; - aoa = .03; - maxDoppler = 0; - - if ((nb_tx==2) && (nb_rx==1)) { - R_sqrt_ptr2 = R_sqrt_21_corr; - } else if ((nb_tx==2) && (nb_rx==2)) { - R_sqrt_ptr2 = R_sqrt_22_corr; - } else - R_sqrt_ptr2 = NULL; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = .03; + maxDoppler = 0; + + if ((nb_tx==2) && (nb_rx==1)) { + R_sqrt_ptr2 = R_sqrt_21_corr; + } + else if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_corr; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; case Rayleigh1_anticorr: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 1; - aoa = .03; - maxDoppler = 0; - - if ((nb_tx==2) && (nb_rx==1)) { - R_sqrt_ptr2 = R_sqrt_21_anticorr; - } else if ((nb_tx==2) && (nb_rx==2)) { - R_sqrt_ptr2 = R_sqrt_22_anticorr; - } else - R_sqrt_ptr2 = NULL; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = .03; + maxDoppler = 0; + + if ((nb_tx==2) && (nb_rx==1)) { //check this + R_sqrt_ptr2 = R_sqrt_21_anticorr; + } + else if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_anticorr; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; case Rice1: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 0.1; - aoa = .03; - maxDoppler = 0; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 0.1; + aoa = 0.7854; + maxDoppler = 0; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; case AWGN: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 0.0; - aoa = 0.0; - maxDoppler = 0; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - NULL, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 0); - printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor); - - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 0.0; + aoa = 0.0; + maxDoppler = 0; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor); + + break; + + case TS_SHIFT: + nb_taps = 2; + Td = ts_shift_delays[1]; + channel_length = 10; + ricean_factor = 0.0; + aoa = 0.0; + maxDoppler = 0; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + ts_shift_amps, + ts_shift_delays, + NULL, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + printf("TS_SHIFT: ricean_factor %f\n",chan_desc->ricean_factor); + + break; case Rice1_corr: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 0.1; - aoa = .03; - maxDoppler = 0; - - if ((nb_tx==2) && (nb_rx==1)) { - R_sqrt_ptr2 = R_sqrt_21_corr; - } else if ((nb_tx==2) && (nb_rx==2)) { - R_sqrt_ptr2 = R_sqrt_22_corr; - } else - R_sqrt_ptr2 = NULL; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 0.1; + aoa = .03; + maxDoppler = 0; + + if ((nb_tx==2) && (nb_rx==1)) { + R_sqrt_ptr2 = R_sqrt_21_corr; + } + else if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_corr; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); + break; case Rice1_anticorr: - nb_taps = 1; - Td = 0; - channel_length = 1; - ricean_factor = 0.1; - aoa = .03; - maxDoppler = 0; - - if ((nb_tx==2) && (nb_rx==1)) { - R_sqrt_ptr2 = R_sqrt_21_anticorr; - } else if ((nb_tx==2) && (nb_rx==2)) { - R_sqrt_ptr2 = R_sqrt_22_anticorr; - } else - R_sqrt_ptr2 = NULL; - - fill_channel_desc(chan_desc,nb_tx, - nb_rx, - nb_taps, - channel_length, - default_amp_lin, - NULL, - R_sqrt_ptr2, - Td, - sampling_rate, - channel_bandwidth, - ricean_factor, - aoa, - forgetting_factor, - maxDoppler, - channel_offset, - path_loss_dB, - 1); - break; + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 0.1; + aoa = .03; + maxDoppler = 0; + + if ((nb_tx==2) && (nb_rx==1)) { + R_sqrt_ptr2 = R_sqrt_21_anticorr; + } + else if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_anticorr; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); + break; + + case Rayleigh1_orthogonal: + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = 0.03; + maxDoppler = 0; + + + if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_orthogonal; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; + + case Rayleigh1_orth_eff_ch_TM4_prec_real: + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = 0.03; + maxDoppler = 0; + + + if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 1); + break; + + case Rayleigh1_orth_eff_ch_TM4_prec_imag: + nb_taps = 1; + Td = 0; + channel_length = 1; + ricean_factor = 1; + aoa = 0.03; + maxDoppler = 0; + + + if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc,nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amp_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; + + case Rayleigh8_orth_eff_ch_TM4_prec_real: + + if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; + //R_sqrt_ptr2 = NULL; + } + else + R_sqrt_ptr2 = NULL; + + + nb_taps = 8; + Td = 0.8; + channel_length = (int)11+2*sampling_rate*Td; + ricean_factor = 1; + aoa = .03; + maxDoppler = 0; + + fill_channel_desc(chan_desc, + nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amps_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + + break; + + case Rayleigh8_orth_eff_ch_TM4_prec_imag: + nb_taps = 8; + Td = 0.8; + channel_length = (int)11+2*sampling_rate*Td; + ricean_factor = 1; + aoa = .03; + maxDoppler = 0; + + if ((nb_tx==2) && (nb_rx==2)) { + R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; + } + else + R_sqrt_ptr2 = NULL; + + fill_channel_desc(chan_desc, + nb_tx, + nb_rx, + nb_taps, + channel_length, + default_amps_lin, + NULL, + R_sqrt_ptr2, + Td, + sampling_rate, + channel_bandwidth, + ricean_factor, + aoa, + forgetting_factor, + maxDoppler, + channel_offset, + path_loss_dB, + 0); + break; default: LOG_W(OCM,"channel model not yet supported\n"); free(chan_desc); return(NULL); } - LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor); - - for (i=0; i<chan_desc->nb_taps; i++) + for (i=0;i<chan_desc->nb_taps;i++) LOG_D(OCM,"[CHANNEL] tap %d: amp %f, delay %f\n",i,chan_desc->amps[i],chan_desc->delays[i]); chan_desc->nb_paths = 10; @@ -870,8 +1203,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } -int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) -{ +int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { double s; int i,k,l,aarx,aatx; @@ -884,10 +1216,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) } start_meas(&desc->random_channel); - - for (i=0; i<(int)desc->nb_taps; i++) { - for (aarx=0; aarx<desc->nb_rx; aarx++) { - for (aatx=0; aatx<desc->nb_tx; aatx++) { + for (i=0;i<(int)desc->nb_taps;i++) { + for (aarx=0;aarx<desc->nb_rx;aarx++) { + for (aatx=0;aatx<desc->nb_tx;aatx++) { anew[aarx+(aatx*desc->nb_rx)].x = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); anew[aarx+(aatx*desc->nb_rx)].y = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); @@ -906,7 +1237,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) anew[aarx+(aatx*desc->nb_rx)].x += phase.x * sqrt(1.0-desc->ricean_factor); anew[aarx+(aatx*desc->nb_rx)].y += phase.y * sqrt(1.0-desc->ricean_factor); } - #ifdef DEBUG_CH printf("(%d,%d,%d) %f->(%f,%f) (%f,%f) phase (%f,%f)\n",aarx,aatx,i,desc->amps[i],anew[aarx+(aatx*desc->nb_rx)].x,anew[aarx+(aatx*desc->nb_rx)].y,desc->aoa,desc->ricean_factor,phase.x,phase.y); #endif @@ -917,9 +1247,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) // for debugging set a=anew; for (aarx=0;aarx<desc->nb_rx;aarx++) { for (aatx=0;aatx<desc->nb_tx;aatx++) { - desc->a[i][aarx+(aatx*desc->nb_rx)].x = anew[aarx+(aatx*desc->nb_rx)].x; - desc->a[i][aarx+(aatx*desc->nb_rx)].y = anew[aarx+(aatx*desc->nb_rx)].y; - printf("anew(%d,%d) = %f+1j*%f\n",aatx,aarx,anew[aarx+(aatx*desc->nb_rx)].x, anew[aarx+(aatx*desc->nb_rx)].y); + desc->a[i][aarx+(aatx*desc->nb_rx)].x = anew[aarx+(aatx*desc->nb_rx)].x; + desc->a[i][aarx+(aatx*desc->nb_rx)].y = anew[aarx+(aatx*desc->nb_rx)].y; + printf("anew(%d,%d) = %f+1j*%f\n",aatx,aarx,anew[aarx+(aatx*desc->nb_rx)].x, anew[aarx+(aatx*desc->nb_rx)].y); } } */ @@ -937,16 +1267,17 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) /* for (aarx=0;aarx<desc->nb_rx;aarx++) { for (aatx=0;aatx<desc->nb_tx;aatx++) { - desc->a[i][aarx+(aatx*desc->nb_rx)].x = acorr[aarx+(aatx*desc->nb_rx)].x; - desc->a[i][aarx+(aatx*desc->nb_rx)].y = acorr[aarx+(aatx*desc->nb_rx)].y; - printf("tap %d, acorr1(%d,%d) = %f+1j*%f\n",i,aatx,aarx,acorr[aarx+(aatx*desc->nb_rx)].x, acorr[aarx+(aatx*desc->nb_rx)].y); + desc->a[i][aarx+(aatx*desc->nb_rx)].x = acorr[aarx+(aatx*desc->nb_rx)].x; + desc->a[i][aarx+(aatx*desc->nb_rx)].y = acorr[aarx+(aatx*desc->nb_rx)].y; + printf("tap %d, acorr1(%d,%d) = %f+1j*%f\n",i,aatx,aarx,acorr[aarx+(aatx*desc->nb_rx)].x, acorr[aarx+(aatx*desc->nb_rx)].y); } } */ - if (desc->first_run==1) { + if (desc->first_run==1){ cblas_zcopy(desc->nb_tx*desc->nb_rx, (void*) acorr, 1, (void*) desc->a[i], 1); - } else { + } + else { // a = alpha*acorr+beta*a // a = beta*a // a = a+alpha*acorr @@ -964,15 +1295,14 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) /* for (aarx=0;aarx<desc->nb_rx;aarx++) { for (aatx=0;aatx<desc->nb_tx;aatx++) { - //desc->a[i][aarx+(aatx*desc->nb_rx)].x = acorr[aarx+(aatx*desc->nb_rx)].x; - //desc->a[i][aarx+(aatx*desc->nb_rx)].y = acorr[aarx+(aatx*desc->nb_rx)].y; - printf("tap %d, a(%d,%d) = %f+1j*%f\n",i,aatx,aarx,desc->a[i][aarx+(aatx*desc->nb_rx)].x, desc->a[i][aarx+(aatx*desc->nb_rx)].y); + //desc->a[i][aarx+(aatx*desc->nb_rx)].x = acorr[aarx+(aatx*desc->nb_rx)].x; + //desc->a[i][aarx+(aatx*desc->nb_rx)].y = acorr[aarx+(aatx*desc->nb_rx)].y; + printf("tap %d, a(%d,%d) = %f+1j*%f\n",i,aatx,aarx,desc->a[i][aarx+(aatx*desc->nb_rx)].x, desc->a[i][aarx+(aatx*desc->nb_rx)].y); } } */ } //nb_taps - stop_meas(&desc->random_channel); //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex)); @@ -1005,14 +1335,14 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) } //nb_taps #ifdef DEBUG_CH - printf("(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); + k=0; + printf("(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); #endif - } - } //channel_length - } //aatx - } //aarx - - stop_meas(&desc->interp_time); + } + } //channel_length + } //aatx + } //aarx + stop_meas(&desc->interp_time); } if (desc->first_run==1) @@ -1028,22 +1358,22 @@ double N_RB2sampling_rate(uint16_t N_RB) case 6: sampling_rate = 1.92; break; - + case 25: sampling_rate = 7.68; break; - + case 50: sampling_rate = 15.36; break; - + case 100: sampling_rate = 30.72; break; - + default: LOG_E(PHY,"Unknown N_PRB\n"); - return(-1); + return(-1); } return(sampling_rate); @@ -1056,22 +1386,22 @@ double N_RB2channel_bandwidth(uint16_t N_RB) case 6: channel_bandwidth = 1.25; break; - + case 25: channel_bandwidth = 5.00; break; - + case 50: channel_bandwidth = 10.00; break; - + case 100: channel_bandwidth = 20.00; break; - + default: LOG_E(PHY,"Unknown N_PRB\n"); - return(-1); + return(-1); } return(channel_bandwidth); } @@ -1079,8 +1409,7 @@ double N_RB2channel_bandwidth(uint16_t N_RB) #ifdef RANDOM_CHANNEL_MAIN #define sampling_rate 5.0 #define Td 2.0 -main(int argc,char **argv) -{ +main(int argc,char **argv) { double amps[8] = {.8,.2,.1,.04,.02,.01,.005}; struct complex ch[(int)(1+2*sampling_rate*Td)],phase; diff --git a/openair1/SIMULATION/TOOLS/rangen_double.c b/openair1/SIMULATION/TOOLS/rangen_double.c index a1dee2a55382127c4530980b880c3dcb104d7e79..69f255bec3db4bca1c30cb159ea93c0c2eaa0715 100644 --- a/openair1/SIMULATION/TOOLS/rangen_double.c +++ b/openair1/SIMULATION/TOOLS/rangen_double.c @@ -39,13 +39,41 @@ static unsigned int seed, iy, ir[98]; #define a 1664525lu #define mod 4294967296.0 /* is 2**32 */ +#if 1 +void randominit(unsigned seed_init) +{ + int i; + // this need to be integrated with the existing rng, like taus: navid + msg("Initializing random number generator, seed %x\n",seed_init); + + if (seed_init == 0) { + srand((unsigned)time(NULL)); + + seed = (unsigned int) rand(); + } else { + seed = seed_init; + } + if (seed % 2 == 0) seed += 1; /* seed and mod are relative prime */ + + for (i=1; i<=97; i++) { + seed = a*seed; /* mod 2**32 */ + ir[i]= seed; /* initialize the shuffle table */ + } + + iy=1; +} +#endif + +#if 0 void randominit(unsigned seed_init) { int i; // this need to be integrated with the existing rng, like taus: navid msg("Initializing random number generator, seed %x\n",seed_init); + seed_init = 62110; + if (seed_init == 0) { srand((unsigned)time(NULL)); @@ -63,7 +91,7 @@ void randominit(unsigned seed_init) iy=1; } - +#endif /*!\brief Uniform linear congruential random number generator on \f$[0,1)\f$. Returns a double-precision floating-point number.*/ double uniformrandom(void) diff --git a/openair1/SIMULATION/TOOLS/taus.c b/openair1/SIMULATION/TOOLS/taus.c index 326c743e695255da71ca9d4ec027335b4cc28367..e8a13da0768048b32bb7e59eb96813c1a841d9b9 100644 --- a/openair1/SIMULATION/TOOLS/taus.c +++ b/openair1/SIMULATION/TOOLS/taus.c @@ -19,86 +19,124 @@ * contact@openairinterface.org */ -#ifdef USER_MODE -#include <time.h> -#include <stdlib.h> -#else -#include <asm/io.h> -#include <asm/rtai.h> -#endif -#ifdef RTAI_ENABLED -#include <rtai.h> -#include <rtai_sched.h> -#define time(x) (unsigned int)(rt_get_time_ns()) -#endif - -unsigned int s0, s1, s2, b; - -//---------------------------------------------- -// -/*! -*/ -// - -unsigned int taus(void) -{ - - b = (((s0 << 13) ^ s0) >> 19); - s0 = (((s0 & 0xFFFFFFFE) << 12)^ b); - b = (((s1 << 2) ^ s1) >> 25); - s1 = (((s1 & 0xFFFFFFF8) << 4)^ b); - b = (((s2 << 3) ^ s2) >> 11); - s2 = (((s2 & 0xFFFFFFF0) << 17)^ b); - return s0 ^ s1 ^ s2; -} - -void set_taus_seed(unsigned int seed_init) -{ - -#ifdef USER_MODE - struct drand48_data buffer; - unsigned long result = 0; -#endif - - if (seed_init == 0) { - s0 = (unsigned int)time(NULL); - s1 = (unsigned int)time(NULL); - s2 = (unsigned int)time(NULL); - } else { -#ifndef USER_MODE - s0 = (unsigned int)0x1e23d852; - s1 = (unsigned int)0x81f38a1c; - s2 = (unsigned int)0xfe1a133e; -#else - /* Use reentrant version of rand48 to ensure that no conflicts with other generators occur */ - srand48_r((long int)seed_init, &buffer); - mrand48_r(&buffer, (long int *)&result); - s0 = result; - mrand48_r(&buffer, (long int *)&result); - s1 = result; - mrand48_r(&buffer, (long int *)&result); - s2 = result; -#endif - } -} - -#ifdef MAIN - -main() -{ - - unsigned int i,rand; - - set_taus_seed(); - - for (i=0; i<10; i++) { - - rand = taus(); - printf("%u\n",rand); - - } -} -#endif //MAIN - - - +#ifdef USER_MODE +#include <time.h> +#include <stdlib.h> +#else +#include <asm/io.h> +#include <asm/rtai.h> +#endif +#ifdef RTAI_ENABLED +#include <rtai.h> +#include <rtai_sched.h> +#define time(x) (unsigned int)(rt_get_time_ns()) +#endif + +unsigned int s0, s1, s2, b; + +//---------------------------------------------- +// +/*! +*/ +// + +unsigned int taus(void) +{ + + b = (((s0 << 13) ^ s0) >> 19); + s0 = (((s0 & 0xFFFFFFFE) << 12)^ b); + b = (((s1 << 2) ^ s1) >> 25); + s1 = (((s1 & 0xFFFFFFF8) << 4)^ b); + b = (((s2 << 3) ^ s2) >> 11); + s2 = (((s2 & 0xFFFFFFF0) << 17)^ b); + return s0 ^ s1 ^ s2; +} +#if 1 +void set_taus_seed(unsigned int seed_init) +{ + +#ifdef USER_MODE + struct drand48_data buffer; + unsigned long result = 0; +#endif + + if (seed_init == 0) { + s0 = (unsigned int)time(NULL); + s1 = (unsigned int)time(NULL); + s2 = (unsigned int)time(NULL); + } else { +#ifndef USER_MODE + s0 = (unsigned int)0x1e23d852; + s1 = (unsigned int)0x81f38a1c; + s2 = (unsigned int)0xfe1a133e; +#else + /* Use reentrant version of rand48 to ensure that no conflicts with other generators occur */ + srand48_r((long int)seed_init, &buffer); + mrand48_r(&buffer, (long int *)&result); + s0 = result; + mrand48_r(&buffer, (long int *)&result); + s1 = result; + mrand48_r(&buffer, (long int *)&result); + s2 = result; +#endif + } +} +#endif + +#if 0 + void set_taus_seed(unsigned int seed_init) +{ + +#ifdef USER_MODE + struct drand48_data buffer; + unsigned long result = 0; +#endif + s0 = (unsigned int)0x1e23d852; + s1 = (unsigned int)0x81f38a1c; + s2 = (unsigned int)0xfe1a133e; + + return; + + if (seed_init == 0) { + s0 = (unsigned int)time(NULL); + s1 = (unsigned int)time(NULL); + s2 = (unsigned int)time(NULL); + } else { +#ifndef USER_MODE + s0 = (unsigned int)0x1e23d852; + s1 = (unsigned int)0x81f38a1c; + s2 = (unsigned int)0xfe1a133e; +#else + // Use reentrant version of rand48 to ensure that no conflicts with other generators occur */ + srand48_r((long int)seed_init, &buffer); + mrand48_r(&buffer, (long int *)&result); + s0 = result; + mrand48_r(&buffer, (long int *)&result); + s1 = result; + mrand48_r(&buffer, (long int *)&result); + s2 = result; +#endif + } +} +#endif + +#ifdef MAIN + +main() +{ + + unsigned int i,rand; + + set_taus_seed(); + + for (i=0; i<10; i++) { + + rand = taus(); + printf("%u\n",rand); + + } +} +#endif //MAIN + + + diff --git a/openair2/COMMON/commonDef.h b/openair2/COMMON/commonDef.h index b1ec47449af1a7f0da1fa7257c16db49ad7eda6d..37d05f3fda8a858737384a3627c6a6306a2d7bbc 100644 --- a/openair2/COMMON/commonDef.h +++ b/openair2/COMMON/commonDef.h @@ -316,15 +316,6 @@ typedef struct { */ #define TAI_LIST_T(SIZE) struct {Byte_t n_tais; tai_t tai[SIZE];} -/* - * User notification callback, executed whenever a change of data with - * respect of network information (e.g. network registration and/or - * location change, new PLMN becomes available) is notified by the - * EPS Mobility Management sublayer - */ -typedef int (*emm_indication_callback_t) (Stat_t, tac_t, ci_t, AcT_t, - const char*, size_t); - typedef enum eps_protocol_discriminator_e { /* Protocol discriminator identifier for EPS Mobility Management */ EPS_MOBILITY_MANAGEMENT_MESSAGE = 0x7, diff --git a/openair2/COMMON/mac_rrc_primitives.h b/openair2/COMMON/mac_rrc_primitives.h index dfa641ee66531f911bb3fd253392892a8822457f..9a8c363b02a23c5ef8a77761a4fba3b70c146f8f 100644 --- a/openair2/COMMON/mac_rrc_primitives.h +++ b/openair2/COMMON/mac_rrc_primitives.h @@ -33,7 +33,7 @@ #include "RadioResourceConfigCommonSIB.h" #include "RadioResourceConfigDedicated.h" #include "MeasGapConfig.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MBSFN-AreaInfoList-r9.h" #include "MBSFN-SubframeConfigList.h" #endif @@ -380,7 +380,7 @@ typedef struct { TDD_Config_t *tdd_Config, uint8_t *SIwindowsize, uint16_t *SIperiod -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , MBMS_flag_t MBMS_Flag, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList, @@ -388,9 +388,9 @@ typedef struct { struct PMCH_InfoList_r9 *pmch_InfoList #endif ); - unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, char*); + unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, const unsigned int,char*); void (*mac_rlc_data_ind)(module_id_t, logical_chan_id_t, char*, tb_size_t, num_tb_t, crc_t* ); - mac_rlc_status_resp_t (*mac_rlc_status_ind) (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP, + mac_rlc_status_resp_t (*mac_rlc_status_ind) (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, sub_frame_t subframeP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP, logical_chan_id_t channel_idP, tb_size_t tb_sizeP); signed int (*rrc_rlc_data_req)(module_id_t, rb_id_t, mui_t, confirm_t, sdu_size_t, char *); void (*rrc_rlc_register_rrc) (void (*rrc_data_indP)(module_id_t , rb_id_t , sdu_size_t , char* ), diff --git a/openair2/COMMON/networkDef.h b/openair2/COMMON/networkDef.h index c52a58a527e32faaaa187bb6c976f76a3feb3cf7..42c812baada0127cc8c15c2ad014863f7bbc5523 100644 --- a/openair2/COMMON/networkDef.h +++ b/openair2/COMMON/networkDef.h @@ -252,13 +252,6 @@ typedef struct { network_pkf_t* pkf[NET_PACKET_FILTER_MAX]; } network_tft_t; -/* - * User notification callback, executed whenever a change of status with - * respect of PDN connection or EPS bearer context is notified by the EPS - * Session Management sublayer - */ -typedef int (*esm_indication_callback_t) (int, network_pdn_state_t); - /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h index 6ad9ef078bd5ad42f7951e11abaa7abf5b19a41c..377773b642a4c28dc43e73d77c5bf478e0e0de9e 100644 --- a/openair2/COMMON/platform_constants.h +++ b/openair2/COMMON/platform_constants.h @@ -86,7 +86,7 @@ #define DEFAULT_RAB_ID 1 #define NB_RB_MAX (maxDRB + 3) /* was 11, now 14, maxDRB comes from asn1_constants.h, + 3 because of 3 SRB, one invisible id 0, then id 1 and 2 */ -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) #define NB_RB_MBMS_MAX (maxSessionPerPMCH*maxServiceCount) #else // Do not allocate unused memory diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index b17e7d772424eb18612e9f5796ab27f817bd12f2..45d7774afad0bf382481a644c4fbb4536f243a2a 100644 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -264,7 +264,7 @@ typedef struct protocol_ctxt_s { (Ctxt_Pp)->subframe = sUBfRAME; \ PROTOCOL_CTXT_COMPUTE_MODULE_ID(Ctxt_Pp) -#define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02u][RNTI %"PRIx16"]" +#define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02u][RNTI %" PRIx16 "]" #define PROTOCOL_CTXT_ARGS(CTXT_Pp) \ (CTXT_Pp)->frame, \ ((CTXT_Pp)->enb_flag == ENB_FLAG_YES) ? "eNB":" UE", \ diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 8a4c27f5ebb913c0d1a07302c879dcedb74fe579..0e3cd844d9ed017ba9e8f7ddd7eea16e27a5d4f2 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -122,7 +122,7 @@ typedef struct RrcConfigurationReq_s { long pucch_delta_shift[MAX_NUM_CCs]; long pucch_nRB_CQI[MAX_NUM_CCs]; long pucch_nCS_AN[MAX_NUM_CCs]; -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) long pucch_n1_AN[MAX_NUM_CCs]; #endif long pdsch_referenceSignalPower[MAX_NUM_CCs]; diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 60415aad868e3a8807172e9077a17b2eafb4ee6a..de0d0490aaba8f5f15f534a6cc596caa61046073 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -151,7 +151,7 @@ static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_pro RRC_CONFIGURATION_REQ (msg_p).pucch_delta_shift[CC_id] = enb_properties->properties[enb_id]->pucch_delta_shift[CC_id]; RRC_CONFIGURATION_REQ (msg_p).pucch_nRB_CQI[CC_id] = enb_properties->properties[enb_id]->pucch_nRB_CQI[CC_id]; RRC_CONFIGURATION_REQ (msg_p).pucch_nCS_AN[CC_id] = enb_properties->properties[enb_id]->pucch_nCS_AN[CC_id]; -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) RRC_CONFIGURATION_REQ (msg_p).pucch_n1_AN[CC_id] = enb_properties->properties[enb_id]->pucch_n1_AN[CC_id]; #endif diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 2a48aefbaf81376f6d0058513bdf7e950efa123a..153c89b3e2b2d4fb63461151b155b7607e66666d 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -115,7 +115,7 @@ #define ENB_CONFIG_STRING_PUCCH_DELTA_SHIFT "pucch_delta_shift" #define ENB_CONFIG_STRING_PUCCH_NRB_CQI "pucch_nRB_CQI" #define ENB_CONFIG_STRING_PUCCH_NCS_AN "pucch_nCS_AN" -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) #define ENB_CONFIG_STRING_PUCCH_N1_AN "pucch_n1_AN" #endif #define ENB_CONFIG_STRING_PDSCH_RS_EPRE "pdsch_referenceSignalPower" @@ -208,6 +208,7 @@ #define ENB_CONFIG_STRING_RRH_GW_IQ_TXSHIFT "iq_txshift" #define ENB_CONFIG_STRING_RRH_GW_TX_SAMPLE_ADVANCE "tx_sample_advance" #define ENB_CONFIG_STRING_RRH_GW_TX_SCHEDULING_ADVANCE "tx_scheduling_advance" +#define ENB_CONFIG_STRING_RRH_GW_IF_COMPRESSION "if_compression" #define ENB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity" #define ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE "none" @@ -338,6 +339,7 @@ void enb_config_display(void) } else { printf( "\tRF target : \tNONE:\n"); } + printf( "\tif_compression : \t%s Compression:\n",(enb_properties.properties[i]->rrh_gw_config[j].if_compress == 1)? "ALAW" : "None"); } } @@ -416,7 +418,7 @@ void enb_config_display(void) printf( "\tpucch_delta_shift for CC %d:\t%ld:\n",j,enb_properties.properties[i]->pucch_delta_shift[j]); printf( "\tpucch_nRB_CQI for CC %d:\t%ld:\n",j,enb_properties.properties[i]->pucch_nRB_CQI[j]); printf( "\tpucch_nCS_AN for CC %d:\t%ld:\n",j,enb_properties.properties[i]->pucch_nCS_AN[j]); -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) printf( "\tpucch_n1_AN for CC %d:\t%ld:\n",j,enb_properties.properties[i]->pucch_n1_AN[j]); #endif @@ -425,7 +427,7 @@ void enb_config_display(void) if (enb_properties.properties[i]->srs_enable[j]) { printf( "\tsrs_BandwidthConfig for CC %d:\t%ld:\n",j,enb_properties.properties[i]->srs_BandwidthConfig[j]); - printf( "\tsrs_BandwidthConfig for CC %d:\t%ld:\n",j,enb_properties.properties[i]->srs_SubframeConfig[j]); + printf( "\tsrs_SubframeConfig for CC %d:\t%ld:\n",j,enb_properties.properties[i]->srs_SubframeConfig[j]); printf( "\tsrs_ackNackST for CC %d:\t%d:\n",j,enb_properties.properties[i]->srs_ackNackST[j]); printf( "\tsrs_MaxUpPts for CC %d:\t%d:\n",j,enb_properties.properties[i]->srs_MaxUpPts[j]); } @@ -587,7 +589,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) libconfig_int pucch_delta_shift = 0; libconfig_int pucch_nRB_CQI = 0; libconfig_int pucch_nCS_AN = 0; -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) libconfig_int pucch_n1_AN = 0; #endif libconfig_int pdsch_referenceSignalPower = 0; @@ -657,6 +659,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) char* ipv6 = NULL; char* active = NULL; char* preference = NULL; + char* if_compression = NULL; char* tr_preference = NULL; char* rf_preference = NULL; @@ -865,7 +868,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_PUCCH_DELTA_SHIFT, &pucch_delta_shift) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_PUCCH_NRB_CQI, &pucch_nRB_CQI) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_PUCCH_NCS_AN, &pucch_nCS_AN) -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_PUCCH_N1_AN, &pucch_n1_AN) #endif && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_PDSCH_RS_EPRE, &pdsch_referenceSignalPower) @@ -910,7 +913,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_UETIMERS_N311, &ue_TimersAndConstants_n311) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_UE_TRANSMISSION_MODE, &ue_TransmissionMode) -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #endif )) { @@ -1159,7 +1162,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for pucch_nCS_AN choice: 0..7!\n", lib_config_file_name_pP, i, pucch_nCS_AN); -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) enb_properties.properties[enb_properties_index]->pucch_n1_AN[j] = pucch_n1_AN; if ((pucch_n1_AN <0) || (pucch_n1_AN > 2047)) @@ -1344,21 +1347,21 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) lib_config_file_name_pP, i, pusch_p0_Nominal); if (strcmp(pusch_alpha,"AL0")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al0; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al0; } else if (strcmp(pusch_alpha,"AL04")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al04; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al04; } else if (strcmp(pusch_alpha,"AL05")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al05; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al05; } else if (strcmp(pusch_alpha,"AL06")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al06; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al06; } else if (strcmp(pusch_alpha,"AL07")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al07; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al07; } else if (strcmp(pusch_alpha,"AL08")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al08; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al08; } else if (strcmp(pusch_alpha,"AL09")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al09; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al08; } else if (strcmp(pusch_alpha,"AL1")==0) { - enb_properties.properties[enb_properties_index]->pusch_alpha[j] = UplinkPowerControlCommon__alpha_al1; + enb_properties.properties[enb_properties_index]->pusch_alpha[j] = Alpha_r12_al1; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for pucch_Alpha choice: AL0,AL04,AL05,AL06,AL07,AL08,AL09,AL1!\n", @@ -1550,47 +1553,47 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) switch (rach_preambleTransMax) { case 3: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n3; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n3; break; case 4: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n4; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n4; break; case 5: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n5; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n5; break; case 6: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n6; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n6; break; case 7: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n7; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n7; break; case 8: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n8; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n8; break; case 10: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n10; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n10; break; case 20: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n20; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n20; break; case 50: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n50; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n50; break; case 100: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n100; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n100; break; case 200: - enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n200; + enb_properties.properties[enb_properties_index]->rach_preambleTransMax[j] = PreambleTransMax_n200; break; default: @@ -2327,82 +2330,91 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) // RRH Config setting_rrh_gws = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_RRH_GW_CONFIG); if ( setting_rrh_gws != NULL) { - num_rrh_gw = config_setting_length(setting_rrh_gws); - enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; + num_rrh_gw = config_setting_length(setting_rrh_gws); + enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; - for (j = 0; j < num_rrh_gw; j++) { - setting_rrh_gw = config_setting_get_elem(setting_rrh_gws, j); - - if ( !( - config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME, (const char **)&if_name) - && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS, (const char **)&ipv4) - && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_ADDRESS , (const char **)&ipv4_remote) - && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT, &local_port) - && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT, &remote_port) - && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_ACTIVE, (const char **)&active) - && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TRANSPORT_PREFERENCE, (const char **)&tr_preference) - && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_RF_TARGET_PREFERENCE, (const char **)&rf_preference) - && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_IQ_TXSHIFT, &iq_txshift) - && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TX_SAMPLE_ADVANCE, &tx_sample_advance) - && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TX_SCHEDULING_ADVANCE, &tx_scheduling_advance) - ) - ) { - AssertFatal (0, - "Failed to parse eNB configuration file %s, %u th enb %u the RRH GW address !\n", - lib_config_file_name_pP, i, j); - continue; // FIXME will prevent segfaults below, not sure what happens at function exit... - } - - enb_properties.properties[enb_properties_index]->nb_rrh_gw += 1; - - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rrh_gw_if_name = strdup(if_name); - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_address = strdup(ipv4); - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_address = strdup(ipv4_remote); - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_port = local_port; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_port = remote_port; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].iq_txshift = iq_txshift; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_sample_advance = tx_sample_advance; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_scheduling_advance= tx_scheduling_advance; - - if (strcmp(active, "yes") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].active = 1; - } - - if (strcmp(tr_preference, "udp") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; - } else if (strcmp(tr_preference, "raw") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; - } else if (strcmp(tr_preference, "udp_if4p5") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4p5 = 1; - } else if (strcmp(tr_preference, "raw_if4p5") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4p5 = 1; - } else if (strcmp(tr_preference, "raw_if5_mobipass") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif5_mobipass = 1; - } else {//if (strcmp(preference, "no") == 0) - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; - } - - if (strcmp(rf_preference, "exmimo") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 1; - } else if (strcmp(rf_preference, "usrp_b200") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 1; - } else if (strcmp(rf_preference, "usrp_x300") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 1; - } else if (strcmp(rf_preference, "bladerf") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 1; - } else if (strcmp(rf_preference, "lmsdr") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 1; - } else {//if (strcmp(preference, "no") == 0) + for (j = 0; j < num_rrh_gw; j++) { + setting_rrh_gw = config_setting_get_elem(setting_rrh_gws, j); - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 1; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 1; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 1; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 1; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 1; - - } - } + if ( !( + config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME, (const char **)&if_name) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS, (const char **)&ipv4) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_ADDRESS , (const char **)&ipv4_remote) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT, &local_port) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT, &remote_port) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_ACTIVE, (const char **)&active) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TRANSPORT_PREFERENCE, (const char **)&tr_preference) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_RF_TARGET_PREFERENCE, (const char **)&rf_preference) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_IQ_TXSHIFT, &iq_txshift) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TX_SAMPLE_ADVANCE, &tx_sample_advance) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TX_SCHEDULING_ADVANCE, &tx_scheduling_advance) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_IF_COMPRESSION, (const char **)&if_compression) + ) + ) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, %u th enb %u the RRH GW address !\n", + lib_config_file_name_pP, i, j); + continue; // FIXME will prevent segfaults below, not sure what happens at function exit... + } + + enb_properties.properties[enb_properties_index]->nb_rrh_gw += 1; + + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rrh_gw_if_name = strdup(if_name); + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_address = strdup(ipv4); + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_address = strdup(ipv4_remote); + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_port = local_port; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_port = remote_port; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].iq_txshift = iq_txshift; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_sample_advance = tx_sample_advance; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_scheduling_advance= tx_scheduling_advance; + + if (strcmp(active, "yes") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].active = 1; + } + + if (strcmp(tr_preference, "udp") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; + } else if (strcmp(tr_preference, "raw") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; + } else if (strcmp(tr_preference, "udp_if4p5") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4p5 = 1; + } else if (strcmp(tr_preference, "raw_if4p5") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4p5 = 1; + } else if (strcmp(tr_preference, "raw_if5_mobipass") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif5_mobipass = 1; + } else {//if (strcmp(preference, "no") == 0) + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; + } + + if (strcmp(rf_preference, "exmimo") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 1; + } else if (strcmp(rf_preference, "usrp_b200") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 1; + } else if (strcmp(rf_preference, "usrp_x300") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 1; + } else if (strcmp(rf_preference, "bladerf") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 1; + } else if (strcmp(rf_preference, "lmsdr") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 1; + } else {//if (strcmp(preference, "no") == 0) + + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 1; + + } + + if (strcmp(if_compression, "alaw") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].if_compress = 1; + } else if (strcmp(if_compression, "none") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].if_compress = 0; + } else { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].if_compress = 0; + } + } } else { enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rrh_gw_if_name = "none"; @@ -2421,8 +2433,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 0; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 0; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].if_compress = 0; } - + // SCTP SETTING enb_properties.properties[enb_properties_index]->sctp_out_streams = SCTP_OUT_STREAMS; enb_properties.properties[enb_properties_index]->sctp_in_streams = SCTP_IN_STREAMS; diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index fd53395311c4e3eeef5fda3bb42062c60687b7e8..a508a82e1f627b94c16f6ff5d69cccfe20c2da91 100644 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -85,6 +85,7 @@ typedef struct rrh_gw_config_s { uint8_t udpif4p5; uint8_t rawif4p5; uint8_t rawif5_mobipass; + uint8_t if_compress; int tx_scheduling_advance; int tx_sample_advance; int iq_txshift; @@ -153,7 +154,7 @@ typedef struct Enb_properties_s { long pucch_delta_shift[1+MAX_NUM_CCs]; long pucch_nRB_CQI[1+MAX_NUM_CCs]; long pucch_nCS_AN[1+MAX_NUM_CCs]; -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) long pucch_n1_AN[1+MAX_NUM_CCs]; #endif long pdsch_referenceSignalPower[1+MAX_NUM_CCs]; diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index f2d00145a05c9f752db5544fc14f35acb0ef9d86..073bb8029cfca92266973a5b172f028001c08900 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -562,14 +562,16 @@ int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) { int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) { rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id); uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0); + uint16_t subframe = (uint16_t) flexran_get_current_subframe(mod_id); + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,subframe,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0); return rlc_status.bytes_in_buffer; } int flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) { rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id); uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0); + uint16_t subframe = (uint16_t) flexran_get_current_subframe(mod_id); + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0); return rlc_status.head_sdu_creation_time; } diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index b5d613e4ae4d8e392602a64d4a03cd8752d2e990..ecbe0b68bae612c1e2a334fb191123a6d3a7b01b 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -42,7 +42,7 @@ #include "extern.h" #include "UTIL/LOG/log.h" #include "UTIL/LOG/vcd_signal_dumper.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MBSFN-AreaInfoList-r9.h" #include "MBSFN-AreaInfo-r9.h" #include "MBSFN-SubframeConfigList.h" @@ -93,7 +93,7 @@ rrc_mac_config_req( uint8_t eNB_index, RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, struct PhysicalConfigDedicated *physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) SCellToAddMod_r10_t *sCellToAddMod_r10, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif @@ -110,7 +110,7 @@ rrc_mac_config_req( long *ul_Bandwidth, AdditionalSpectrumEmission_t *additionalSpectrumEmission, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,uint8_t MBMS_Flag, MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList, PMCH_InfoList_r9_t *pmch_InfoList @@ -217,7 +217,7 @@ rrc_mac_config_req( if (mac_MainConfig->ul_SCH_Config->periodicBSR_Timer) { UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = (uint16_t) *mac_MainConfig->ul_SCH_Config->periodicBSR_Timer; } else { - UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = (uint16_t) MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity; + UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer = (uint16_t) PeriodicBSR_Timer_r12_infinity; } if (mac_MainConfig->ul_SCH_Config->maxHARQ_Tx) { @@ -230,11 +230,11 @@ rrc_mac_config_req( if (mac_MainConfig->ul_SCH_Config->retxBSR_Timer) { UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t) mac_MainConfig->ul_SCH_Config->retxBSR_Timer; } else { - UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t)MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560; + UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t)RetxBSR_Timer_r12_sf2560; } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (mac_MainConfig->ext1 && mac_MainConfig->ext1->sr_ProhibitTimer_r9) { UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = (uint16_t) *mac_MainConfig->ext1->sr_ProhibitTimer_r9; @@ -310,7 +310,7 @@ rrc_mac_config_req( } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (sCellToAddMod_r10 != NULL) { @@ -332,15 +332,17 @@ rrc_mac_config_req( if (eNB_flagP == 0) { if (measObj!= NULL) { if (measObj[0]!= NULL) { - UE_mac_inst[Mod_idP].n_adj_cells = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.count; - LOG_I(MAC,"Number of adjacent cells %d\n",UE_mac_inst[Mod_idP].n_adj_cells); + if (measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList != NULL) { + UE_mac_inst[Mod_idP].n_adj_cells = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.count; + LOG_D(MAC,"Number of adjacent cells %d\n",UE_mac_inst[Mod_idP].n_adj_cells); - for (i=0; i<UE_mac_inst[Mod_idP].n_adj_cells; i++) { - UE_mac_inst[Mod_idP].adj_cell_id[i] = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.array[i]->physCellId; - LOG_I(MAC,"Cell %d : Nid_cell %d\n",i,UE_mac_inst[Mod_idP].adj_cell_id[i]); - } + for (i=0; i<UE_mac_inst[Mod_idP].n_adj_cells; i++) { + UE_mac_inst[Mod_idP].adj_cell_id[i] = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.array[i]->physCellId; + LOG_D(MAC,"Cell %d : Nid_cell %d\n",i,UE_mac_inst[Mod_idP].adj_cell_id[i]); + } - mac_xface->phy_config_meas_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].n_adj_cells,UE_mac_inst[Mod_idP].adj_cell_id); + mac_xface->phy_config_meas_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].n_adj_cells,UE_mac_inst[Mod_idP].adj_cell_id); + } } /* @@ -449,7 +451,7 @@ rrc_mac_config_req( eNB_mac_inst[Mod_idP].common_channels[0].mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0]); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) eNB_mac_inst[Mod_idP].common_channels[0].MBMS_flag = MBMS_Flag; #endif } else { // UE @@ -465,7 +467,7 @@ rrc_mac_config_req( } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (mbsfn_AreaInfoList != NULL) { if (eNB_flagP == 1) { diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index 3c0223e59e831476c2fe66db0d22371ecae95b85..18b8e7c38c2f12646ebc5a85c0579ac1fed89668 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -57,7 +57,7 @@ #include "RACH-ConfigCommon.h" #include "MeasObjectToAddModList.h" #include "MobilityControlInfo.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MBSFN-AreaInfoList-r9.h" #include "MBSFN-SubframeConfigList.h" #include "PMCH-InfoList-r9.h" @@ -80,7 +80,7 @@ #define SCH_PAYLOAD_SIZE_MAX 4096 /// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB) -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // Mask for identifying subframe for MBMS #define MBSFN_TDD_SF3 0x80// for TDD @@ -276,7 +276,7 @@ typedef struct { uint8_t payload[PCCH_PAYLOAD_SIZE_MAX] ; } __attribute__((__packed__))PCCH_PDU; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /*! \brief MCCH payload */ typedef struct { uint8_t payload[MCCH_PAYLOAD_SIZE_MAX] ; @@ -327,7 +327,7 @@ typedef struct { /*!\brief LCID of padding LCID for DLSCH */ #define SHORT_PADDING 31 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // MCH LCHAN IDs (table6.2.1-4 TS36.321) /*!\brief LCID of MCCH for DL */ #define MCCH_LCHANID 0 @@ -889,7 +889,7 @@ typedef struct { struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; /// number of subframe allocation pattern available for MBSFN sync area uint8_t num_sf_allocation_pattern; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// MBMS Flag uint8_t MBMS_flag; /// Outgoing MCCH pdu for PHY @@ -1058,7 +1058,7 @@ typedef struct { struct RACH_ConfigDedicated *rach_ConfigDedicated; /// pointer to RRC PHY configuration struct PhysicalConfigDedicated *physicalConfigDedicated; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// pointer to RRC PHY configuration SCEll struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10; #endif @@ -1132,7 +1132,7 @@ typedef struct { struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA? /// number of subframe allocation pattern available for MBSFN sync area uint8_t num_sf_allocation_pattern; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// number of active MBSFN area uint8_t num_active_mbsfn_area; /// MBSFN Area Info diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index dee7c51a6e514178f1521d8c7484fa7ddad7e395..e7fbbce3c9507ad16380810adde1fc9a9cda1478 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -127,7 +127,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { DCI_pdu[CC_id]->Num_common_dci = 0; DCI_pdu[CC_id]->Num_ue_spec_dci = 0; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active =0; #endif eNB_mac_inst[module_idP].frame = frameP; @@ -140,10 +140,14 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, rnti = UE_RNTI(module_idP, i); CC_id = UE_PCCID(module_idP, i); - if ((frameP==0)&&(subframeP==0)) - LOG_I(MAC,"UE rnti %x : %s, PHR %d dB\n", rnti, - UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync", - UE_list->UE_template[CC_id][i].phr_info); + if ((frameP==0)&&(subframeP==0)) { + LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti); + int cqi = eNB_UE_stats == NULL ? -1 : eNB_UE_stats->DL_cqi[0]; + LOG_I(MAC,"UE rnti %x : %s, PHR %d dB CQI %d\n", rnti, + UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync", + UE_list->UE_template[CC_id][i].phr_info, + cqi); + } PHY_vars_eNB_g[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63; if (i==UE_list->head) @@ -305,7 +309,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TODO process CCCH data req. break; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) case RRC_MAC_MCCH_DATA_REQ: LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d, mbsfn_sync_area %d\n", @@ -346,7 +350,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, 0, // eNB index, unused in eNB CC_id); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (eNB_mac_inst[module_idP].common_channels[CC_id].MBMS_flag >0) { @@ -383,10 +387,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->frame_parms->frame_type == FDD) { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,0,4);//,calibration_flag); - } else if ((mac_xface->frame_parms->tdd_config == TDD) || //TDD + } else if ((mac_xface->frame_parms->tdd_config == 0) || //TDD (mac_xface->frame_parms->tdd_config == 3) || (mac_xface->frame_parms->tdd_config == 6)) { - //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag); } #ifndef FLEXRAN_AGENT_SB_IF schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c old mode 100644 new mode 100755 index 41a136d6b1eb2f86e95194a2832b88adaf69c086..68f99bf7218013ee44148f411982a6c739a57819 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -520,25 +520,27 @@ schedule_ue_spec( // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); continue_flag=1; } - - switch(mac_xface->get_transmission_mode(module_idP,CC_id,rnti)){ - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + + if (continue_flag != 1){ + switch(mac_xface->get_transmission_mode(module_idP,CC_id,rnti)){ + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP,CC_id), eNB_UE_stats->DL_cqi[0], format1); - break; - case 3: - aggregation = get_aggregation(get_bw_index(module_idP,CC_id), + break; + case 3: + aggregation = get_aggregation(get_bw_index(module_idP,CC_id), eNB_UE_stats->DL_cqi[0], format2A); - break; - default: - LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(module_idP,CC_id,rnti)); - aggregation = 2; - } - + break; + default: + LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(module_idP,CC_id,rnti)); + aggregation = 2; + } + } /* if (continue_flag != 1 */ + if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti) ) { @@ -610,17 +612,15 @@ schedule_ue_spec( if (round > 0) { - if (frame_parms[CC_id]->frame_type == TDD) { - UE_list->UE_template[CC_id][UE_id].DAI++; - update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI); - LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", - CC_id,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI); - } - // get freq_allocation nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; if (nb_rb <= nb_available_rb) { + if (frame_parms[CC_id]->frame_type == TDD) { + UE_list->UE_template[CC_id][UE_id].DAI++; + update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI); + LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id,subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI); + } if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { for(j=0; j<frame_parms[CC_id]->N_RBG; j++) { // for indicating the rballoc for each sub-band @@ -821,6 +821,7 @@ schedule_ue_spec( rnti, module_idP, frameP, + subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, @@ -839,6 +840,7 @@ schedule_ue_spec( ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, + TBS, //not used (char *)&dlsch_buffer[0]); T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), @@ -872,6 +874,7 @@ schedule_ue_spec( rnti, module_idP, frameP, + subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH+1, @@ -890,6 +893,7 @@ schedule_ue_spec( ENB_FLAG_YES, MBMS_FLAG_NO, DCCH+1, + TBS, //not used (char *)&dlsch_buffer[sdu_length_total]); T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), @@ -932,6 +936,7 @@ schedule_ue_spec( rnti, module_idP, frameP, + subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, @@ -949,6 +954,7 @@ schedule_ue_spec( ENB_FLAG_YES, MBMS_FLAG_NO, lcid, + TBS, //not used (char*)&dlsch_buffer[sdu_length_total]); T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), T_INT(lcid), T_INT(sdu_lengths[num_sdus])); @@ -1440,15 +1446,157 @@ schedule_ue_spec( /* // disabled for now as this needs to be done properly case 4: + if (frame_parms[CC_id]->frame_type == TDD) { + switch (frame_parms[CC_id]->N_RB_DL) { + case 6: + // fall back to alamouti for now + ((DCI2_1_5MHz_2A_TDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_1_5MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_1_5MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_1_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_1_5MHz_2A_TDD_t*)DLSCH_dci)->rv1 = 0; + + // deactivate TB2 + ((DCI2A_1_5MHz_2A_TDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2A_1_5MHz_2A_TDD_t*)DLSCH_dci)->rv2 = 1; + + ((DCI2A_1_5MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; + ((DCI2A_1_5MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc; + break; + + case 25: + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->tpmi = 0; ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs; ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; - ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1; - ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rv1 = round&3; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rv2 = 1; + + LOG_D(MAC,"Format2 DCI: harq_pid %d, ndi %d\n",harq_pid,((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1); + break; + + case 50: + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_10MHz_2A_TDD_t*)DLSCH_dci)->rv2 = 1; + break; + + case 100: + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_20MHz_2A_TDD_t*)DLSCH_dci)->rv2 = 1; + break; + + default: + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rv1 = 0; ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rv2 = 1; + break; + } + } else { + switch (frame_parms[CC_id]->N_RB_DL) { + case 6: + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_1_5MHz_2A_FDD_t*)DLSCH_dci)->rv2 = 1; break; + case 25: + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->rv2 = 1; + + LOG_I(MAC,"Format2 DCI: harq_pid %d, ndi %d\n",harq_pid,((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->ndi1); + break; + + case 50: + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->TPC = tpc; + // deactivate TB2 + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_10MHz_2A_FDD_t*)DLSCH_dci)->rv2 = 1; + break; + + case 100: + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_20MHz_2A_FDD_t*)DLSCH_dci)->rv2 = 1; + break; + + default: + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->tpmi = 0; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->mcs1 = mcs; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->harq_pid = harq_pid; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->ndi1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->rv1 = 0; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->TPC = tpc; + + // deactivate TB2 + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->mcs2 = 0; + ((DCI2_5MHz_2A_FDD_t*)DLSCH_dci)->rv2 = 1; + break; + } + } + + break; + */ + /* + // disabled for now as this needs to be done properly case 5: ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->mcs = mcs; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index 1dac7af70480cf3729724eab6956b3d02a4104a5..56582f936cc714e7de66ba02f2a394805c211809 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -61,7 +61,7 @@ #define DEBUG_eNB_SCHEDULER 1 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) int8_t get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t CC_id, uint8_t mbsfn_sync_area) { // currently there is one-to-one mapping between sf allocation pattern and sync area @@ -87,7 +87,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra unsigned char header_len_mcch=0,header_len_msi=0,header_len_mtch=0, header_len_mtch_temp=0, header_len_mcch_temp=0, header_len_msi_temp=0; int ii=0, msi_pos=0; int mcch_mcs = -1; - uint16_t TBS,j,padding=0,post_padding=0; + uint16_t TBS,j=-1,padding=0,post_padding=0; mac_rlc_status_resp_t rlc_status; int num_mtch; int msi_length,i,k; @@ -466,7 +466,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra } TBS = mac_xface->get_TBS_DL(eNB_mac_inst[module_idP].common_channels[CC_id].MCH_pdu.mcs, mac_xface->frame_parms->N_RB_DL); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // do not let mcch and mtch multiplexing when relaying is active // for sync area 1, so not transmit data //if ((i == 0) && ((eNB_mac_inst[module_idP].MBMS_flag != multicast_relay) || (eNB_mac_inst[module_idP].mcch_active==0))) { @@ -504,7 +504,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra module_idP,CC_id,frameP,MTCH,TBS, TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); - rlc_status = mac_rlc_status_ind(module_idP,0,frameP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH, + rlc_status = mac_rlc_status_ind(module_idP,0,frameP,subframeP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH, TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); LOG_D(MAC,"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d\n", MTCH,frameP,subframeP, rlc_status.bytes_in_buffer); @@ -521,6 +521,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra ENB_FLAG_YES, MBMS_FLAG_YES, MTCH, + 0, //not used (char*)&mch_buffer[sdu_length_total]); //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]); LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",module_idP,CC_id,sdu_lengths[num_sdus],MTCH); @@ -538,7 +539,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // } #endif diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index da9e8572baf6c01b5e666754f81c448ce41db7cd..56ede260e8cacf7cf6ad4a622eda7e46f4841c0d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -525,7 +525,7 @@ void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag) /* - #ifdef Rel10 + #if defined(Rel10) || defined(Rel14) unsigned char generate_mch_header( unsigned char *mac_header, unsigned char num_sdus, unsigned short *sdu_lengths, @@ -769,7 +769,7 @@ int get_bw_index(module_id_t module_id, uint8_t CC_id) default: bw_index=1; - LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting bw_index to 1\n", module_id, CC_id); + LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting bw_index to 1\n", module_id, frame_parms->N_RB_DL, CC_id); break; } diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c index 9c8b23df07a3545188c260f9fbbe7165dfb0ae93..38f39e50e10e613a2f979ae8e32a6eaf0cf1901a 100644 --- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c +++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c @@ -174,6 +174,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, rnti, mod_id, frame, + subframe, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, @@ -193,6 +194,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, rnti, mod_id, frame, + subframe, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, @@ -209,6 +211,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, + rlc_size, //not used (char *)&dlsch_buffer[sdu_length_total]); LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[j]); diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c index 00027f04ce1f46ffdceefbe1bfd0e2b56a16b3e7..5f1df6766340f637634343be389c027dec12d0a0 100644 --- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c +++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c @@ -160,7 +160,7 @@ void _store_dlsch_buffer (module_id_t Mod_id, for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels - rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); + rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; @@ -1241,6 +1241,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id, rnti, mod_id, frame, + subframe, ENB_FLAG_YES, MBMS_FLAG_NO, j, diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index d812ec0087a892f0144e11c2172f79f83eecce2d..e04d7c3b8ad14f7b069ca8147be8712399c1bfea 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -62,24 +62,27 @@ #endif //PHY_EMUL #include "SCHED/defs.h" - +/* TODO: this abstraction_flag here is very hackish - find a proper solution */ +extern uint8_t abstraction_flag; void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) //init as MR { LOG_D(MAC,"[UE %d] Frame %d: PHY Sync to eNB_index %d successful \n", module_idP, frameP, eNB_index); -#if ! defined(ENABLE_USE_MME) +#if defined(ENABLE_USE_MME) + int mme_enabled=1; +#else + int mme_enabled=0; +#endif - if (first_sync==1) { + if (first_sync==1 && !(mme_enabled==1 && abstraction_flag==0)) { layer2_init_UE(module_idP); openair_rrc_ue_init(module_idP,eNB_index); } else -#endif { rrc_in_sync_ind(module_idP,frameP,eNB_index); } - } void mrbch_phy_sync_failure(module_id_t module_idP, frame_t frameP, uint8_t free_eNB_index) //init as CH @@ -178,7 +181,7 @@ int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, ui #ifdef PHY_EMUL Mac_rlc_xface->Is_cluster_head[Mod_id]=2;//0: MR, 1: CH, 2: not CH neither MR #endif - /*#ifdef Rel10 + /*#if defined(Rel10) || defined(Rel14) int n; for (n=0;n<4096;n++) eNB_mac_inst[Mod_id].MCH_pdu.payload[n] = taus(); @@ -476,7 +479,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->ue_decode_si = ue_decode_si; mac_xface->ue_decode_p = ue_decode_p; mac_xface->ue_send_sdu = ue_send_sdu; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) mac_xface->ue_send_mch_sdu = ue_send_mch_sdu; mac_xface->ue_query_mch = ue_query_mch; #endif @@ -514,7 +517,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->phy_config_sib2_eNB = phy_config_sib2_eNB; mac_xface->phy_config_sib2_ue = phy_config_sib2_ue; mac_xface->phy_config_afterHO_ue = phy_config_afterHO_ue; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) mac_xface->phy_config_sib13_eNB = phy_config_sib13_eNB; mac_xface->phy_config_sib13_ue = phy_config_sib13_ue; #endif @@ -539,7 +542,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->get_prach_prb_offset = get_prach_prb_offset; mac_xface->is_prach_subframe = is_prach_subframe; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) mac_xface->get_mch_sdu = get_mch_sdu; mac_xface->phy_config_dedicated_scell_eNB= phy_config_dedicated_scell_eNB; mac_xface->phy_config_dedicated_scell_ue= phy_config_dedicated_scell_ue; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 6e73e353f019954e954e757ac10b4984e48d2731..1be9a2ba3a112b128927a2d4addfcb3d3c314461 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -66,14 +66,29 @@ */ /* this function checks that get_eNB_UE_stats returns - * a non-NULL pointer for all CCs for a given UE + * a non-NULL pointer for all the active CCs of an UE */ int phy_stats_exist(module_id_t Mod_id, int rnti) { int CC_id; - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + int i; + int UE_id = find_UE_id(Mod_id, rnti); + UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; + if (UE_id == -1) { + LOG_W(MAC, "[eNB %d] UE %x not found, should be there (in phy_stats_exist)\n", + Mod_id, rnti); + return 0; + } + if (UE_list->numactiveCCs[UE_id] == 0) { + LOG_W(MAC, "[eNB %d] UE %x has no active CC (in phy_stats_exist)\n", + Mod_id, rnti); + return 0; + } + for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { + CC_id = UE_list->ordered_CCids[i][UE_id]; if (mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti) == NULL) return 0; + } return 1; } @@ -109,7 +124,7 @@ void store_dlsch_buffer (module_id_t Mod_id, for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels - rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); + rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index 77a60794cc7fd039650379369b8e83330b3e99f4..ea264f1bfdfed36579df9d7f5b2b7e6c162b9ea7 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -405,7 +405,7 @@ void ue_decode_p(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_ind void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, sub_frame_t subframe, uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /* \brief Called by PHY to transfer MCH transport block to ue MAC. @param Mod_id Index of module instance @param frame Frame index @@ -454,6 +454,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,u @param t_crnti Pointer to PHY variable containing the T_CRNTI @param preamble_index Preamble Index used by PHY to transmit the PRACH. This should match the received RAR to trigger the rest of random-access procedure +@param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload @returns timing advance or 0xffff if preamble doesn't match */ uint16_t @@ -464,7 +465,8 @@ ue_process_rar( const rnti_t ra_rnti, uint8_t * const dlsch_buffer, rnti_t * const t_crnti, - const uint8_t preamble_index + const uint8_t preamble_index, + uint8_t* selected_rar_buffer ); @@ -754,7 +756,7 @@ int rrc_mac_config_req(module_id_t module_idP, uint8_t eNB_index, RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, struct PhysicalConfigDedicated *physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) SCellToAddMod_r10_t *sCellToAddMod_r10, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif @@ -771,7 +773,7 @@ int rrc_mac_config_req(module_id_t module_idP, long *ul_Bandwidth, AdditionalSpectrumEmission_t *additionalSpectrumEmission, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , uint8_t MBMS_Flag, MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList, diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c index 43bc1137985aedfb39e6e9a0f84e92f1e30ccca3..d2d52383b007c34a0a7b98417fbd58147fee6194 100644 --- a/openair2/LAYER2/MAC/ra_procedures.c +++ b/openair2/LAYER2/MAC/ra_procedures.c @@ -394,7 +394,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) { // This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example) dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element - rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, + rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, DCCH, 6); @@ -409,6 +409,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, + 6, //not used (char *)&ulsch_buff[0]); LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]); @@ -499,37 +500,37 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, (rach_ConfigCommon->powerRampingParameters.powerRampingStep<<1); // 2dB increments in ASN.1 definition int preambleTransMax = -1; switch (rach_ConfigCommon->ra_SupervisionInfo.preambleTransMax) { - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n3: + case PreambleTransMax_n3: preambleTransMax = 3; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n4: + case PreambleTransMax_n4: preambleTransMax = 4; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n5: + case PreambleTransMax_n5: preambleTransMax = 5; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n6: + case PreambleTransMax_n6: preambleTransMax = 6; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n7: + case PreambleTransMax_n7: preambleTransMax = 7; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n8: + case PreambleTransMax_n8: preambleTransMax = 8; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n10: + case PreambleTransMax_n10: preambleTransMax = 10; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n20: + case PreambleTransMax_n20: preambleTransMax = 20; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n50: + case PreambleTransMax_n50: preambleTransMax = 50; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n100: + case PreambleTransMax_n100: preambleTransMax = 100; break; - case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n200: + case PreambleTransMax_n200: preambleTransMax = 200; break; } diff --git a/openair2/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c index 2de22c067affe4fae4833400f5d735e77de4d9c0..51900d8f3a655dbce4cd10b62e1a6b0f21a48ed5 100644 --- a/openair2/LAYER2/MAC/rar_tools.c +++ b/openair2/LAYER2/MAC/rar_tools.c @@ -136,15 +136,48 @@ ue_process_rar( const rnti_t ra_rnti, uint8_t* const dlsch_buffer, rnti_t* const t_crnti, - const uint8_t preamble_index + const uint8_t preamble_index, + uint8_t* selected_rar_buffer // output argument for storing the selected RAR header and RAR payload ) //------------------------------------------------------------------------------ { + uint16_t ret = 0; // return value RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer; // RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1); uint8_t *rar = (uint8_t *)(dlsch_buffer+1); + // get the last RAR payload for working with CMW500 + uint8_t n_rarpy = 0; // number of RAR payloads + uint8_t n_rarh = 0; // number of MAC RAR subheaders + uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs + while (1) { + n_rarh++; + if (rarh->T == 1) { + n_rarpy++; + LOG_D(MAC, "RAPID %d\n", rarh->RAPID); + } + + if (rarh->RAPID == preamble_index) { + LOG_D(PHY, "Found RAR with the intended RAPID %d\n", rarh->RAPID); + rar = (uint8_t *)(dlsch_buffer+n_rarh + (n_rarpy-1)*6); + break; + } + + if (abs((int)rarh->RAPID - (int)preamble_index) < abs((int)best_rx_rapid - (int)preamble_index)) { + best_rx_rapid = rarh->RAPID; + rar = (uint8_t *)(dlsch_buffer+n_rarh + (n_rarpy-1)*6); + } + + if (rarh->E == 0) { + LOG_I(PHY, "No RAR found with the intended RAPID. The closest RAPID in all RARs is %d\n", best_rx_rapid); + break; + } else { + rarh++; + } + }; + LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n", n_rarh, n_rarpy); + if (CC_id>0) { LOG_W(MAC,"Should not have received RAR on secondary CCs! \n"); return(0xffff); @@ -172,7 +205,7 @@ ue_process_rar( if (opt_enabled) { LOG_D(OPT,"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n", module_idP, CC_id, frameP, ra_rnti); - trace_pdu(1, (uint8_t*)rarh, 7, module_idP, 2, ra_rnti, + trace_pdu(1, (uint8_t*)dlsch_buffer, n_rarh + n_rarpy*6, module_idP, 2, ra_rnti, UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0); } @@ -180,9 +213,16 @@ ue_process_rar( *t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti; UE_mac_inst[module_idP].crnti = *t_crnti;//rar->t_crnti; //return(rar->Timing_Advance_Command); - return((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); + ret = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); } else { UE_mac_inst[module_idP].crnti=0; - return(0xffff); + ret = (0xffff); } + + // move the selected RAR to the front of the RA_PDSCH buffer + memcpy(selected_rar_buffer+0, (uint8_t*)rarh, 1); + memcpy(selected_rar_buffer+1, (uint8_t*)rar , 6); + + return ret; + } diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 6d304051d4c06c59a0de7dbbdca623e3d1b841c8..f9488ce5437d97169a94b90f1d9a39d9afe800fb 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -93,8 +93,8 @@ void ue_init_mac(module_id_t module_idP) // default values as deined in 36.331 sec 9.2.2 LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP); //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL; - UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240; - UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity; + UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= RetxBSR_Timer_r12_sf10240; + UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=PeriodicBSR_Timer_r12_infinity; UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; @@ -353,7 +353,7 @@ ue_send_sdu( if (opt_enabled) { trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti, - UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0); + frameP, subframeP, 0, 0); LOG_D(OPT,"[UE %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n", module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len); } @@ -579,7 +579,7 @@ void ue_decode_p(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_in } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) unsigned char *parse_mch_header(unsigned char *mac_header, unsigned char *num_sdu, unsigned char *rx_lcids, @@ -1265,13 +1265,13 @@ unsigned char generate_ulsch_header(uint8_t *mac_header, void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen, uint8_t *access_mode) { - mac_rlc_status_resp_t rlc_status; uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ; uint16_t buflen_remain = 0; uint8_t bsr_len=0,bsr_ce_len=0,bsr_header_len=0; uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0; uint8_t lcid=0,lcid_rlc_pdu_count=0; boolean_t is_lcid_processed = FALSE; + boolean_t is_all_lcid_processed = FALSE; uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t payload_offset=0,num_sdus=0; @@ -1291,6 +1291,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf int lcg_id_bsr_trunc = 0; int highest_priority = 16; int num_lcg_id_with_data = 0; + rlc_buffer_occupancy_t lcid_buffer_occupancy_old=0, lcid_buffer_occupancy_new=0; LOG_D(MAC,"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", module_idP, frameP, subframe, buflen); @@ -1352,7 +1353,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf } // periodicBSR-Timer expires, trigger BSR - if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity) + if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF == 0)){ // Trigger BSR Periodic UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PERIODIC; @@ -1400,16 +1401,32 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf // check for UL bandwidth requests and add SR control element // Check for DCCH first -// TO DO: Unrool the loop to do it at least once to avoid the if num_sdu -for (lcid=DCCH; lcid < DTCH ; lcid++) { +// TO DO: Multiplex in the order defined by the logical channel prioritization +for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid++) { if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) { - is_lcid_processed = FALSE; lcid_rlc_pdu_count = 0; + is_lcid_processed = FALSE; + lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + subframe, + ENB_FLAG_NO, + lcid); + + lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; + + AssertFatal (lcid_buffer_occupancy_new == UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid], "LCID=%d RLC has BO %d bytes but MAC has stored %d bytes\n", + lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]); + + AssertFatal (lcid_buffer_occupancy_new <= UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], "LCID=%d RLC has more BO %d bytes than BSR = %d bytes\n", + lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]); + //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data //Adjust at the end of the loop - while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) { + while ((!is_lcid_processed) && (lcid_buffer_occupancy_new) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) { // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU if ((usim_test == 0) && (lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) { @@ -1420,253 +1437,103 @@ for (lcid=DCCH; lcid < DTCH ; lcid++) { buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1); - rlc_status = mac_rlc_status_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, // eNB_index - lcid, - buflen_remain); - - // Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO - if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] < rlc_status.bytes_in_buffer) { - - LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n", - module_idP,frameP,subframe, - lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count); - - // Skip multiplexing for the LCID - break; - } - - /* - AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d Frame %d Subrame %d\n", - lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe); - */ - - if (rlc_status.bytes_in_buffer > 0) { - - - LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RLC SRB%d has %d bytes to " - "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", - module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]); - - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - (char *)&ulsch_buff[sdu_length_total]); + LOG_D(MAC, "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " + "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", + module_idP,frameP, lcid,lcid_buffer_occupancy_new,buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]); - AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", - lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + lcid, + buflen_remain, + (char *)&ulsch_buff[sdu_length_total]); + AssertFatal (buflen_remain >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", + lcid,sdu_lengths[num_sdus],buflen_remain); - sdu_length_total += sdu_lengths[num_sdus]; - sdu_lcids[num_sdus] = lcid; - LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for SRB%d\n",module_idP,sdu_lengths[num_sdus],lcid); - //header_len +=2; - // update LCID remain buffer - UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus]; - /* Update BSR : substract transmitted data */ - if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){ - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ; - } - else { - LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n", - module_idP,frameP,subframe, - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], - UE_mac_inst[module_idP].scheduling_info.LCGID[lcid], - sdu_lengths[num_sdus],lcid); - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0; - } - - //Update the number of LCGID with data as BSR shall reflect status after BSR transmission - if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)) - { - num_lcg_id_with_data --; - // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1 - if ((bsr_len) && (num_lcg_id_with_data == 1)) - { - bsr_ce_len = sizeof(BSR_SHORT); - bsr_len = bsr_ce_len + bsr_header_len; - } - } - - if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) { - //No more remaining TBS after this PDU - //exit the function - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - } - else { - rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ; - - //Change to 1 byte if it does not fit in the TBS, ie last PDU - if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) { - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - } - } - - //Update number of SDU - num_sdus ++; - - //Update total MAC Header size for RLC PDUs and save last one - total_rlc_pdu_header_len += rlc_pdu_header_len_last; + if (sdu_lengths[num_sdus]) + { + sdu_length_total += sdu_lengths[num_sdus]; + sdu_lcids[num_sdus] = lcid; + LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LcId%d\n",module_idP,sdu_lengths[num_sdus],lcid); + + if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) { + //No more remaining TBS after this PDU + //exit the function + rlc_pdu_header_len_last = 1; + is_lcid_processed = TRUE; + is_all_lcid_processed = TRUE; + } + else { + rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ; + + //Change to 1 byte if it does not fit in the TBS, ie last PDU + if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) { + rlc_pdu_header_len_last = 1; + is_lcid_processed = TRUE; + is_all_lcid_processed = TRUE; + } + } + + //Update number of SDU + num_sdus ++; + + //Update total MAC Header size for RLC PDUs and save last one + total_rlc_pdu_header_len += rlc_pdu_header_len_last; + + lcid_rlc_pdu_count ++; + } + else + { + /* avoid infinite loop ... */ + is_lcid_processed = TRUE; + } - } //end if (rlc_status.bytes_in_buffer > 0) - else { - // Switch to next LCID or exit the whole loop - is_lcid_processed = TRUE; - } - lcid_rlc_pdu_count ++; - } + /* Get updated BO after multiplexing this PDU */ + lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, + UE_mac_inst[module_idP].crnti, + eNB_index, + frameP, + subframe, + ENB_FLAG_NO, + lcid); - UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY; + is_lcid_processed = (is_lcid_processed) || (lcid_buffer_occupancy_new <= 0); } -} - -// Now Check for DTCH first -// TO DO: do it according to Logical Channel Prioritization if at least 2 DTCH -for (lcid=DTCH; lcid < MAX_NUM_LCID ; lcid++) { -if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) { + //Update Buffer remain and BSR bytes after transmission - is_lcid_processed = FALSE; - lcid_rlc_pdu_count = 0; + AssertFatal (lcid_buffer_occupancy_new <= lcid_buffer_occupancy_old, "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n", + lcid_buffer_occupancy_new,lcid_buffer_occupancy_old,lcid,lcid_rlc_pdu_count,frameP,subframe); - //Multiplex all available DTCH RLC PDUs considering to multiplex the last PDU each time for maximize the data - //Adjust at the end of the loop - while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) { + UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new; + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] += (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old); - buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1); - - rlc_status = mac_rlc_status_ind(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, // eNB_index - lcid, - buflen_remain); - - // Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO - if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] < rlc_status.bytes_in_buffer) { - - LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n", - module_idP,frameP,subframe, - lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count); - - // Skip multiplexing for the LCID - break; - } - - /* - AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d Frame %d Subrame %d\n", - lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe); - */ - - if (rlc_status.bytes_in_buffer > 0) { - - - LOG_D(MAC, "[UE %d] Frame %d : UL-DTCH -> ULSCH, RLC LCID%d has %d bytes to " - "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", - module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]); - - - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - UE_mac_inst[module_idP].crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - (char *)&ulsch_buff[sdu_length_total]); - - AssertFatal (sdu_lengths[num_sdus] < MAX_ULSCH_PAYLOAD_BYTES, "LCID=%d RLC PDU size = %d is too big\n", - lcid,sdu_lengths[num_sdus]); - - - AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", - lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]); - - - - sdu_length_total += sdu_lengths[num_sdus]; - sdu_lcids[num_sdus] = lcid; - LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LCID%d\n",module_idP,sdu_lengths[num_sdus],lcid); - //header_len +=2; - // update LCID remain buffer - UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus]; - /* Update BSR : substract transmitted data */ - if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){ - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ; - } - else { - LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n", - module_idP,frameP,subframe, - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], - UE_mac_inst[module_idP].scheduling_info.LCGID[lcid], - sdu_lengths[num_sdus],lcid); - UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0; - } - - //Update the number of LCGID with data as BSR shall reflect status after BSR transmission - if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)) + //Update the number of LCGID with data as BSR shall reflect status after BSR transmission + if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)) + { + num_lcg_id_with_data --; + // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1 + if ((bsr_len) && (num_lcg_id_with_data == 1)) { - num_lcg_id_with_data --; - // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1 - if ((bsr_len) && (num_lcg_id_with_data == 1)) - { - bsr_ce_len = sizeof(BSR_SHORT); - bsr_len = bsr_ce_len + bsr_header_len; - } - + bsr_ce_len = sizeof(BSR_SHORT); + bsr_len = bsr_ce_len + bsr_header_len; } + } - if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) { - //No more remaining TBS after this PDU - //exit the function - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - } - else { - rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ; - - //Change to 1 byte if it does not fit in the TBS, ie last PDU - if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) { - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - } - } - - //Update number of SDU - num_sdus ++; - - //Update total MAC Header size for RLC PDUs and save last one - total_rlc_pdu_header_len += rlc_pdu_header_len_last; - } //end if (rlc_status.bytes_in_buffer > 0) - else { - // Switch to next LCID or exit the whole loop - is_lcid_processed = TRUE; - } - lcid_rlc_pdu_count ++; + UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY; + } } - UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY; - } -} - //lcgid= get_bsr_lcgid(module_idP); // Compute BSR Values and update Nb LCGID with data after multiplexing num_lcg_id_with_data = 0; @@ -1904,7 +1771,7 @@ if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) UE_mac_inst[module_idP].scheduling_info.retxBSR_SF); // Reset Periodic Timer except when BSR is truncated - if ((bsr_t == NULL) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity)) + if ((bsr_t == NULL) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity)) { UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer); @@ -1923,7 +1790,7 @@ if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) if (opt_enabled) { trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0); LOG_D(OPT,"[UE %d][ULSCH] Frame %d subframe %d trace pdu for rnti %x with size %d\n", - module_idP, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, UE_mac_inst[module_idP].crnti, buflen); + module_idP, frameP, subframe, UE_mac_inst[module_idP].crnti, buflen); } } @@ -2104,7 +1971,7 @@ ue_scheduler( /* if (lcid == DCCH) { LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d Pending data for SRB1=%d for LCGID %d \n", - module_idP, frameP,subframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], + module_idP, txFrameP,txSubframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], // UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]); } */ @@ -2396,9 +2263,9 @@ boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subfra lcgid_buffer_remain[lcgid] += UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]; } - rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, + rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, lcid, - 0); + 0xFFFF); //TBS is not used in RLC at this step, set a special value for debug lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer; @@ -2530,63 +2397,63 @@ int get_sf_periodicBSRTimer(uint8_t sf_offset) { switch (sf_offset) { - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf5: + case PeriodicBSR_Timer_r12_sf5: return 5; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf10: + case PeriodicBSR_Timer_r12_sf10: return 10; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf16: + case PeriodicBSR_Timer_r12_sf16: return 16; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf20: + case PeriodicBSR_Timer_r12_sf20: return 20; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf32: + case PeriodicBSR_Timer_r12_sf32: return 32; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf40: + case PeriodicBSR_Timer_r12_sf40: return 40; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf64: + case PeriodicBSR_Timer_r12_sf64: return 64; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf80: + case PeriodicBSR_Timer_r12_sf80: return 80; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf128: + case PeriodicBSR_Timer_r12_sf128: return 128; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf160: + case PeriodicBSR_Timer_r12_sf160: return 160; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf320: + case PeriodicBSR_Timer_r12_sf320: return 320; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf640: + case PeriodicBSR_Timer_r12_sf640: return 640; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf1280: + case PeriodicBSR_Timer_r12_sf1280: return 1280; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf2560: + case PeriodicBSR_Timer_r12_sf2560: return 2560; break; - case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity: + case PeriodicBSR_Timer_r12_infinity: default: return 0xFFFF; break; @@ -2597,27 +2464,27 @@ int get_sf_retxBSRTimer(uint8_t sf_offset) { switch (sf_offset) { - case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf320: + case RetxBSR_Timer_r12_sf320: return 320; break; - case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf640: + case RetxBSR_Timer_r12_sf640: return 640; break; - case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf1280: + case RetxBSR_Timer_r12_sf1280: return 1280; break; - case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560: + case RetxBSR_Timer_r12_sf2560: return 2560; break; - case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf5120: + case RetxBSR_Timer_r12_sf5120: return 5120; break; - case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240: + case RetxBSR_Timer_r12_sf10240: return 10240; break; diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h index edd8548e642f02c8722207cad6fb15ce219e6989..434a9e7c9c9fed8dc5a82a3fb0d19d71ff190a5f 100644 --- a/openair2/LAYER2/MAC/vars.h +++ b/openair2/LAYER2/MAC/vars.h @@ -132,7 +132,7 @@ DCI1A_5MHz_TDD_1_6_t BCCH_alloc_pdu; DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; DCI1_5MHz_TDD_t DLSCH_alloc_pdu; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) DCI1C_5MHz_t MCCH_alloc_pdu; #endif diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 4c67f80e207a84f42a56ed0d7cafbed9f7a1b26c..8dad83a90a71d4a26d155b4be46f3a158df8c469 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -816,6 +816,14 @@ pdcp_data_ind( ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id; #if defined(OAI_EMU) ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = ctxt_pP->module_id + oai_emulation.info.nb_enb_local - oai_emulation.info.first_ue_local; +#else +# if defined(ENABLE_USE_MME) + /* for the UE compiled in S1 mode, we need 1 here + * for the UE compiled in noS1 mode, we need 0 + * TODO: be sure of this + */ + ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = 1; +# endif #endif } else { ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * maxDRB); @@ -1062,7 +1070,7 @@ rrc_pdcp_config_asn1_req ( uint8_t *const kRRCenc_pP, uint8_t *const kRRCint_pP, uint8_t *const kUPenc_pP -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,PMCH_InfoList_r9_t* const pmch_InfoList_r9_pP #endif ,rb_id_t *const defaultDRB @@ -1089,7 +1097,7 @@ rrc_pdcp_config_asn1_req ( hashtable_rc_t h_rc; hash_key_t key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_defaultDRB_rc; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) int i,j; MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL; MBMS_SessionInfo_r9_t *MBMS_SessionInfo_p = NULL; @@ -1387,7 +1395,7 @@ rrc_pdcp_config_asn1_req ( } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (pmch_InfoList_r9_pP != NULL) { for (i=0; i<pmch_InfoList_r9_pP->list.count; i++) { @@ -1582,7 +1590,7 @@ pdcp_config_req_asn1 ( memset(pdcp_pP, 0, sizeof(pdcp_t)); break; -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) case CONFIG_ACTION_MBMS_ADD: case CONFIG_ACTION_MBMS_MODIFY: @@ -1900,7 +1908,7 @@ void pdcp_layer_init(void) { module_id_t instance; -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) mbms_session_id_t session_id; mbms_service_id_t service_id; #endif @@ -1912,7 +1920,7 @@ void pdcp_layer_init(void) AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed"); for (instance = 0; instance < NUMBER_OF_UE_MAX; instance++) { -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) for (service_id = 0; service_id < maxServiceCount; service_id++) { for (session_id = 0; session_id < maxSessionPerPMCH; session_id++) { @@ -1926,7 +1934,7 @@ void pdcp_layer_init(void) for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) { -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) for (service_id = 0; service_id < maxServiceCount; service_id++) { for (session_id = 0; session_id < maxSessionPerPMCH; session_id++) { diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index 366f79dc9db9a7bf2ca68aa5907781c642c939f6..94084273d15b5254859875c0bb8aa4975eb40c5d 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -74,7 +74,7 @@ #include "DRB-ToAddModList.h" #include "SRB-ToAddMod.h" #include "SRB-ToAddModList.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MBMS-SessionInfoList-r9.h" #include "PMCH-InfoList-r9.h" #endif @@ -184,7 +184,7 @@ typedef struct pdcp_s { } pdcp_t; -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) typedef struct pdcp_mbms_s { boolean_t instanciated_instance; rb_id_t rb_id; @@ -284,7 +284,7 @@ public_pdcp( uint8_t *const kRRCenc, uint8_t *const kRRCint, uint8_t *const kUPenc -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,PMCH_InfoList_r9_t *pmch_InfoList_r9 #endif ,rb_id_t *const defaultDRB @@ -448,7 +448,7 @@ public_pdcp(pdcp_stats_t eNB_pdcp_stats[NUMBER_OF_eNB_MAX];) protected_pdcp(rnti_t pdcp_UE_UE_module_id_to_rnti[NUMBER_OF_UE_MAX];) protected_pdcp(rnti_t pdcp_eNB_UE_instance_to_rnti[NUMBER_OF_UE_MAX];) // for noS1 mode protected_pdcp(unsigned int pdcp_eNB_UE_instance_to_rnti_index;) -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) public_pdcp(pdcp_mbms_t pdcp_mbms_array_ue[NUMBER_OF_UE_MAX][maxServiceCount][maxSessionPerPMCH];) // some constants from openair2/RRC/LITE/MESSAGES/asn1_constants.h public_pdcp(pdcp_mbms_t pdcp_mbms_array_eNB[NUMBER_OF_eNB_MAX][maxServiceCount][maxSessionPerPMCH];) // some constants from openair2/RRC/LITE/MESSAGES/asn1_constants.h #endif diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index e380bc6098bd6e7e98d8d6bb5558435e6fb2fc89..2ebcf64cad6db3fac635da1cdeafcd064b90918d 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -167,7 +167,8 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP) ((pdcp_data_ind_header_t *) sdu_p->data)->data_size); #else #if ! defined(OAI_EMU) - ((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0; + /* TODO: do we have to reset to 0 or not? not for a scenario with 1 UE at least */ +// ((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0; #endif #endif @@ -430,7 +431,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) if ((data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV6_TYPE_MULTICAST) /*TRAFFIC_IPV6_TYPE_MULTICAST */ || (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_MULTICAST) /*TRAFFIC_IPV4_TYPE_MULTICAST */ || (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_BROADCAST) /*TRAFFIC_IPV4_TYPE_BROADCAST */ ) { -#if defined (Rel10) +#if defined(Rel10) || defined(Rel14) PDCP_TRANSMISSION_MODE_TRANSPARENT; #else pdcp_mode= PDCP_TRANSMISSION_MODE_DATA; @@ -544,7 +545,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) pdcp_read_state_g = 0; // print_active_requests() #ifdef PDCP_DEBUG - LOG_D(PDCP, "[PDCP][NETLINK] Something in socket, length %d \n", + LOG_D(PDCP, "[PDCP][NETLINK] Something in socket, length %zu\n", nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr)); #endif @@ -571,7 +572,8 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) pdcp_read_header_g.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local : pdcp_read_header_g.inst + oai_emulation.info.first_enb_local;*/ #else // OAI_EMU - pdcp_read_header_g.inst = 0; + /* TODO: do we have to reset to 0 or not? not for a scenario with 1 UE at least */ +// pdcp_read_header_g.inst = 0; //#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id" ctxt.frame = ctxt_cpy.frame; ctxt.enb_flag = ctxt_cpy.enb_flag; @@ -601,7 +603,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) if (h_rc == HASH_TABLE_OK) { #ifdef PDCP_DEBUG - LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n", + LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) on Rab %d \n", ctxt.frame, pdcp_read_header_g.inst, len, @@ -691,7 +693,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) if (h_rc == HASH_TABLE_OK) { rab_id = pdcp_p->rb_id; #ifdef PDCP_DEBUG - LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n", + LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) on Rab %d \n", ctxt.frame, pdcp_read_header_g.inst, len, diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c index 4051a88ef2976da6f625e280329d0ba6cb2af71e..03fabf47b31facd3d84479c1a7cc874713cfc88c 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c @@ -43,61 +43,148 @@ #include "DL-AM-RLC.h" +//----------------------------------------------------------------------------- +uint32_t +rlc_am_get_status_pdu_buffer_occupancy( + rlc_am_entity_t * const rlc_pP){ + + //Compute Max Status PDU size according to what has been received and not received in the window [vrR vrMS[ + + // minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1 + uint32_t nb_bits_to_transmit = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS; + mem_block_t *cursor_p = rlc_pP->receiver_buffer.head; + rlc_am_pdu_info_t *pdu_info_cursor_p = NULL; + int waited_so = 0; + + rlc_sn_t sn_cursor = rlc_pP->vr_r; + rlc_sn_t sn_prev = rlc_pP->vr_r; + rlc_sn_t sn_end = rlc_pP->vr_ms; + boolean_t segment_loop_end = false; + + + if (sn_prev != sn_end) + { + while ((RLC_AM_DIFF_SN(sn_prev,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)) && (cursor_p != NULL)) + { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + sn_cursor = pdu_info_cursor_p->sn; + + // Add holes between sn_prev and sn_cursor + while ((sn_prev != sn_cursor) && (sn_prev != sn_end)) + { + /* Add 1 NACK_SN + E1 + E2 */ + nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1)); + sn_prev = RLC_AM_NEXT_SN(sn_prev); + } //end while (sn_prev != sn_cursor) + + /* Handle case sn_cursor is partially received */ + /* Each gap will add NACK_SN + E1 + E2 + SOStart + SOEnd */ + if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) && (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r))) + { + /* Check lsf */ + segment_loop_end = (pdu_info_cursor_p->lsf == 1); + + /* Fill for [0 SO[ if SO not null */ + if (pdu_info_cursor_p->so) { + nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)); + waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size; + } + else { + waited_so = pdu_info_cursor_p->payload_size; + } + + /* Go to next segment */ + cursor_p = cursor_p->next; + if (cursor_p != NULL) + { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + + /* Fill following gaps if any */ + while (!segment_loop_end) + { + if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)) + { + /* Check lsf */ + segment_loop_end = (pdu_info_cursor_p->lsf == 1); + + if (waited_so < pdu_info_cursor_p->so) { + nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)); + } + else { + /* contiguous segment: only update waited_so */ + /* Assuming so and payload_size updated according to duplication removal done at reception ... */ + waited_so += pdu_info_cursor_p->payload_size; + } + + /* Go to next received PDU or PDU Segment */ + cursor_p = cursor_p->next; + if (cursor_p != NULL) + { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + else + { + /* Fill last gap assuming LSF is not received */ + nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)); + segment_loop_end = true; + } + } // end while (!segment_loop_end) + } // end if segments + else + { + /* Go to next received PDU or PDU segment with different SN */ + do + { + cursor_p = cursor_p->next; + } while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.sn == sn_cursor)); + } + + sn_prev = RLC_AM_NEXT_SN(sn_cursor); + } + } // end if (sn_prev != sn_end) + + // round up to the greatest byte + return ((nb_bits_to_transmit + 7) >> 3); + +} + //----------------------------------------------------------------------------- uint32_t rlc_am_get_buffer_occupancy_in_bytes ( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP) { - uint32_t max_li_overhead; - uint32_t header_overhead; - // priority of control trafic rlc_pP->status_buffer_occupancy = 0; - if (rlc_pP->status_requested) { - if (rlc_pP->t_status_prohibit.running == 0) { + if ((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK)) { + rlc_pP->status_buffer_occupancy = rlc_am_get_status_pdu_buffer_occupancy(rlc_pP); #if TRACE_RLC_AM_BO - if (((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3) > 0) { LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - ((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3)); - } + rlc_pP->status_buffer_occupancy); #endif - rlc_pP->status_buffer_occupancy = ((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3); - } - } - - // data traffic - if (rlc_pP->nb_sdu_no_segmented <= 1) { - max_li_overhead = 0; - } else { - max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2); - } - - if (rlc_pP->sdu_buffer_occupancy == 0) { - header_overhead = 0; - } else { - header_overhead = 2; } #if TRACE_RLC_AM_BO - if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) { + if ((rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : STATUS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->status_buffer_occupancy); - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retransmission_buffer_occupancy); + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retrans_num_bytes_to_retransmit); LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : SDU BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->sdu_buffer_occupancy, - max_li_overhead, - header_overhead, + 0, + 0, rlc_pP->nb_sdu_no_segmented); } #endif - return rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead; + return rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy; } //----------------------------------------------------------------------------- void @@ -150,12 +237,18 @@ config_req_rlc_am ( PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p)); } } -uint32_t pollPDU_tab[PollPDU_pInfinity+1]= {4,8,16,32,64,128,256,1024}; // What is PollPDU_pInfinity??? 1024 for now +uint16_t pollPDU_tab[PollPDU_pInfinity+1]= {4,8,16,32,64,128,256,RLC_AM_POLL_PDU_INFINITE}; //PollPDU_pInfinity is chosen to 0xFFFF for now uint32_t maxRetxThreshold_tab[UL_AM_RLC__maxRetxThreshold_t32+1]= {1,2,3,4,6,8,16,32}; -uint32_t pollByte_tab[PollByte_spare1]= {25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,10000}; // What is PollByte_kBinfinity??? 10000 for now +uint32_t pollByte_tab[PollByte_spare1]= {25000,50000,75000,100000,125000,250000,375000,500000,750000,1000000,1250000,1500000,2000000,3000000,RLC_AM_POLL_BYTE_INFINITE}; // PollByte_kBinfinity is chosen to 0xFFFFFFFF for now +#if defined(Rel14) +uint32_t PollRetransmit_tab[T_PollRetransmit_spare5]= {5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500,800,1000,2000,4000}; +uint32_t am_t_Reordering_tab[32]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200,1600}; +uint32_t t_StatusProhibit_tab[T_StatusProhibit_spare2]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500,800,1000,1200,1600,2000,2400}; +#else uint32_t PollRetransmit_tab[T_PollRetransmit_spare9]= {5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500}; uint32_t am_t_Reordering_tab[T_Reordering_spare1]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200}; uint32_t t_StatusProhibit_tab[T_StatusProhibit_spare8]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500}; +#endif //----------------------------------------------------------------------------- void config_req_rlc_am_asn1 ( @@ -178,9 +271,15 @@ void config_req_rlc_am_asn1 ( if ((config_am_pP->ul_AM_RLC.maxRetxThreshold <= UL_AM_RLC__maxRetxThreshold_t32) && (config_am_pP->ul_AM_RLC.pollPDU<=PollPDU_pInfinity) && (config_am_pP->ul_AM_RLC.pollByte<PollByte_spare1) && +#if defined(Rel14) + (config_am_pP->ul_AM_RLC.t_PollRetransmit<T_PollRetransmit_spare5) && + (config_am_pP->dl_AM_RLC.t_Reordering<32) && + (config_am_pP->dl_AM_RLC.t_StatusProhibit<T_StatusProhibit_spare2) ) { +#else (config_am_pP->ul_AM_RLC.t_PollRetransmit<T_PollRetransmit_spare9) && (config_am_pP->dl_AM_RLC.t_Reordering<T_Reordering_spare1) && (config_am_pP->dl_AM_RLC.t_StatusProhibit<T_StatusProhibit_spare8) ) { +#endif MSC_LOG_RX_MESSAGE( (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE, @@ -306,7 +405,7 @@ rlc_am_get_pdus ( rlc_am_entity_t * const rlc_pP ) { - int display_flag = 0; + //int display_flag = 0; // 5.1.3.1 Transmit operations // 5.1.3.1.1 // General @@ -323,7 +422,8 @@ rlc_am_get_pdus ( case RLC_DATA_TRANSFER_READY_STATE: // TRY TO SEND CONTROL PDU FIRST - if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) { + if ((rlc_pP->nb_bytes_requested_by_mac >= 2) && + ((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK))) { // When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall: // - if t-StatusProhibit is not running: // - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer; @@ -334,140 +434,39 @@ rlc_am_get_pdus ( // // When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall: // - start t-StatusProhibit. - if (rlc_pP->t_status_prohibit.running == 0) { + rlc_am_send_status_pdu(ctxt_pP, rlc_pP); mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list); if (pdu) { list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer); - rlc_pP->status_requested = 0; + RLC_AM_CLEAR_ALL_STATUS(rlc_pP->status_requested); rlc_pP->status_buffer_occupancy = 0; rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP); return; } - } else { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU BECAUSE T-STATUS-PROHIBIT RUNNING (TIME-OUT %u)\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->t_status_prohibit.ms_time_out); } + else { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU (Available MAC Data %u)(T-PROHIBIT %u) (DELAY FLAG %u)\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + rlc_pP->nb_bytes_requested_by_mac,rlc_pP->t_status_prohibit.ms_time_out,(rlc_pP->status_requested & RLC_AM_STATUS_TRIGGERED_DELAYED)); } - /*while ((rlc_pP->nb_bytes_requested_by_mac > 0) && (stay_on_this_list)) { - mem_block_t* pdu = list_get_head(&rlc_pP->control_pdu_list); - if (pdu != NULL { - if ( ((rlc_am_tx_control_pdu_management_t*)(pdu->data))->size <= rlc_pP->nb_bytes_requested_by_mac) { - pdu = list_remove_head(&rlc_pP->control_pdu_list); - #if TRACE_RLC_AM_TX - msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND CONTROL PDU\n", ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, ctxt_pP->frame); - #endif - list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer); - rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - ((rlc_am_tx_control_pdu_management_t*)(pdu->data))->size; - } else { - stay_on_this_list = 0; - } - } else { - stay_on_this_list = 0; - } - }*/ // THEN TRY TO SEND RETRANS PDU - if (rlc_pP->first_retrans_pdu_sn >= 0) { - rlc_am_tx_data_pdu_management_t* tx_data_pdu_management; - - // tx min 3 bytes because of the size of the RLC header - while ((rlc_pP->nb_bytes_requested_by_mac > 2) && - (rlc_pP->first_retrans_pdu_sn >= 0) && - (rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s)) { - - tx_data_pdu_management = &rlc_pP->pdu_retrans_buffer[rlc_pP->first_retrans_pdu_sn]; - - if ((tx_data_pdu_management->header_and_payload_size <= rlc_pP->nb_bytes_requested_by_mac) && (tx_data_pdu_management->retx_count >= 0) - && (tx_data_pdu_management->nack_so_start == 0) && (tx_data_pdu_management->nack_so_stop == 0x7FFF)) { - mem_block_t* copy = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn); - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RE-SEND DATA PDU SN %04d %d BYTES\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn, - tx_data_pdu_management->header_and_payload_size); - rlc_pP->stat_tx_data_pdu += 1; - rlc_pP->stat_tx_retransmit_pdu += 1; - rlc_pP->stat_tx_retransmit_pdu_by_status += 1; - rlc_pP->stat_tx_data_bytes += tx_data_pdu_management->header_and_payload_size; - rlc_pP->stat_tx_retransmit_bytes += tx_data_pdu_management->header_and_payload_size; - rlc_pP->stat_tx_retransmit_bytes_by_status += tx_data_pdu_management->header_and_payload_size; - - list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer); - rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - tx_data_pdu_management->header_and_payload_size; - - tx_data_pdu_management->retx_count += 1; - return; - } else if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac >= RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d MAC BYTES %d SIZE %d RTX COUNT %d nack_so_start %d nack_so_stop %04X(hex)\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn, - rlc_pP->nb_bytes_requested_by_mac, - tx_data_pdu_management->header_and_payload_size, - tx_data_pdu_management->retx_count, - tx_data_pdu_management->nack_so_start, - tx_data_pdu_management->nack_so_stop); - - mem_block_t* copy = rlc_am_retransmit_get_subsegment( - ctxt_pP, - rlc_pP, - rlc_pP->first_retrans_pdu_sn, - &rlc_pP->nb_bytes_requested_by_mac); - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn, - tx_data_pdu_management->nack_so_start); - - rlc_pP->stat_tx_data_pdu += 1; - rlc_pP->stat_tx_retransmit_pdu += 1; - rlc_pP->stat_tx_retransmit_pdu_by_status += 1; - rlc_pP->stat_tx_data_bytes += (((struct mac_tb_req*)(copy->data))->tb_size); - rlc_pP->stat_tx_retransmit_bytes += (((struct mac_tb_req*)(copy->data))->tb_size); - rlc_pP->stat_tx_retransmit_bytes_by_status += (((struct mac_tb_req*)(copy->data))->tb_size); - list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer); - } else { - break; - } + if ((rlc_pP->retrans_num_bytes_to_retransmit) && (rlc_pP->nb_bytes_requested_by_mac > 2)) { - // update first_retrans_pdu_sn - while ((rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s) && - (!(rlc_pP->pdu_retrans_buffer[rlc_pP->first_retrans_pdu_sn].flags.retransmit))) { - rlc_pP->first_retrans_pdu_sn = (rlc_pP->first_retrans_pdu_sn+1) & RLC_AM_SN_MASK; - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn SN %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn); - }; - - display_flag = 1; - - if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) { - // no more pdu to be retransmited - rlc_pP->first_retrans_pdu_sn = -1; - display_flag = 0; - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CLEAR first_retrans_pdu_sn\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); - } + /* Get 1 AM data PDU or PDU segment to retransmit */ + mem_block_t* pdu_retx = rlc_am_get_pdu_to_retransmit(ctxt_pP, rlc_pP); - if (display_flag > 0) { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn); - } + if (pdu_retx != NULL) { + list_add_tail_eurecom (pdu_retx, &rlc_pP->pdus_to_mac_layer); - return; - - /* ONLY ONE TB PER TTI - if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) { - #if TRACE_RLC_AM_TX - msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BREAK LOOP ON RETRANSMISSION BECAUSE ONLY %d BYTES ALLOWED TO TRANSMIT BY MAC\n",ctxt_pP->frame, ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, rlc_pP->nb_bytes_requested_by_mac); - #endif - break; - }*/ - } - } + return; + } + } - if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) { + // THEN TRY TO SEND NEW DATA PDU + if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->sdu_buffer_occupancy) && (rlc_pP->vt_s != rlc_pP->vt_ms)) { rlc_am_segment_10(ctxt_pP, rlc_pP); list_add_list (&rlc_pP->segmentation_pdu_list, &rlc_pP->pdus_to_mac_layer); @@ -478,29 +477,6 @@ rlc_am_get_pdus ( } } - if ((rlc_pP->pdus_to_mac_layer.head == NULL) && - (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP)) && - (rlc_pP->nb_bytes_requested_by_mac > 2)) { - rlc_am_retransmit_any_pdu(ctxt_pP, rlc_pP); - return; - } else { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" COULD NOT RETRANSMIT ANY PDU BECAUSE ", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); - - if (rlc_pP->pdus_to_mac_layer.head != NULL) { - LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT "); - } - - if (!(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP))) { - LOG_D(RLC, "TIMER POLL DID NOT TIMED OUT (RUNNING = %d NUM PDUS TO RETRANS = %d NUM BYTES TO RETRANS = %d) ", rlc_pP->t_poll_retransmit.running, - rlc_pP->retrans_num_pdus, rlc_pP->retrans_num_bytes_to_retransmit); - } - - if (rlc_pP->nb_bytes_requested_by_mac <= 2) { - LOG_D(RLC, "NUM BYTES REQUESTED BY MAC = %d", rlc_pP->nb_bytes_requested_by_mac); - } - LOG_D(RLC, "\n"); - } break; @@ -542,7 +518,8 @@ rlc_am_mac_status_indication ( const protocol_ctxt_t* const ctxt_pP, void * const rlc_pP, const uint16_t tb_sizeP, - struct mac_status_ind tx_statusP) + struct mac_status_ind tx_statusP, + const eNB_flag_t enb_flagP) { struct mac_status_resp status_resp; uint16_t sdu_size = 0; @@ -566,18 +543,38 @@ rlc_am_mac_status_indication ( */ if (rlc->input_sdus == NULL) return status_resp; - if (rlc->last_frame_status_indication != ctxt_pP->frame) { + if (rlc->last_absolute_subframe_status_indication != (PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP))) { rlc_am_check_timer_poll_retransmit(ctxt_pP, rlc); rlc_am_check_timer_reordering(ctxt_pP, rlc); rlc_am_check_timer_status_prohibit(ctxt_pP, rlc); } - rlc->last_frame_status_indication = ctxt_pP->frame; + rlc->last_absolute_subframe_status_indication = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP); rlc->nb_bytes_requested_by_mac = tb_sizeP; status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc); + // For eNB scheduler : Add Max RLC header size for new PDU + // For UE : do not add RLC header part to be compliant with BSR definition in 36.321 + if (enb_flagP == ENB_FLAG_YES) { + uint32_t max_li_overhead = 0; + uint32_t header_overhead = 0; + + if (rlc->nb_sdu_no_segmented > 1) { + /* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/ + uint32_t num_li = rlc->nb_sdu_no_segmented - 1; + max_li_overhead = num_li + (num_li >> 1) + (num_li & 1); + } + + if (rlc->sdu_buffer_occupancy > 0) { + header_overhead = 2; + } + + status_resp.buffer_occupancy_in_bytes += (header_overhead + max_li_overhead); + } + + if ((rlc->input_sdus[rlc->current_sdu_index].mem_block != NULL) && (status_resp.buffer_occupancy_in_bytes)) { //status_resp.buffer_occupancy_in_bytes += ((rlc_am_entity_t *) rlc)->tx_header_min_length_in_bytes; @@ -598,32 +595,16 @@ rlc_am_mac_status_indication ( } } else { - if (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc)) { - if ((status_resp.buffer_occupancy_in_bytes == 0) && (rlc->input_sdus[rlc->current_sdu_index].mem_block == NULL) && (rlc->nb_sdu > 0)) { - // force BO to be > 0 - rlc_sn_t sn = (rlc->vt_s - 1) & RLC_AM_SN_MASK; - rlc_sn_t sn_end = (rlc->vt_a - 1) & RLC_AM_SN_MASK; - int found_pdu = 0; - rlc_sn_t found_pdu_sn = 0; // avoid warning - (void)found_pdu_sn; /* avoid gcc warning "set but not used" */ - - - while (sn != sn_end) { - if (rlc->pdu_retrans_buffer[sn].mem_block != NULL) { - if (!found_pdu) { - found_pdu = 1; - found_pdu_sn = sn; - } - status_resp.buffer_occupancy_in_bytes = rlc->pdu_retrans_buffer[sn].header_and_payload_size; - status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu; - status_resp.head_sdu_remaining_size_to_send = status_resp.buffer_occupancy_in_bytes; - // TODO head_sdu_is_segmented - break; + /* Not so many possibilities ... */ + /* either buffer_occupancy_in_bytes = 0 and that's it */ + /* or we have segmented all received SDUs and buffer occupancy is then made of retransmissions and/or status pdu pending */ + /* then consider only retransmission buffer for the specific BO values used by eNB scheduler (not used up to now...) */ + if (rlc->retrans_num_bytes_to_retransmit) { + status_resp.buffer_occupancy_in_pdus = rlc->retrans_num_pdus; + status_resp.head_sdu_remaining_size_to_send = rlc->retrans_num_bytes_to_retransmit; + status_resp.head_sdu_is_segmented = 1; } } - } - } - } #if MESSAGE_CHART_GENERATOR_RLC_MAC MSC_LOG_RX_MESSAGE( (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE, @@ -666,11 +647,23 @@ rlc_am_mac_status_indication ( #endif return status_resp; } + +//----------------------------------------------------------------------------- +void +rlc_am_set_nb_bytes_requested_by_mac ( + void * const rlc_pP, + const tb_size_t tb_sizeP +) +{ + ((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP; +} + //----------------------------------------------------------------------------- struct mac_data_req rlc_am_mac_data_request ( const protocol_ctxt_t* const ctxt_pP, - void * const rlc_pP + void * const rlc_pP, + const eNB_flag_t enb_flagP ) { struct mac_data_req data_req; @@ -708,7 +701,10 @@ rlc_am_mac_data_request ( data_req.data.nb_elements); } + if (enb_flagP) { + // redundant in UE MAC Tx processing and not used in eNB ... data_req.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, l_rlc_p); + } data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state; #if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR @@ -1255,14 +1251,19 @@ rlc_am_data_req ( l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.no_new_sdu_segmented_in_last_pdu = 0; //l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].li_index_for_discard = -1; l_rlc_p->next_sdu_index = (l_rlc_p->next_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE; - LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ size %d Bytes, NB SDU %d current_sdu_index=%d next_sdu_index=%d conf %d mui %d\n", + if (l_rlc_p->channel_id <3) + { + LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ size %d Bytes, NB SDU %d current_sdu_index=%d next_sdu_index=%d conf %d mui %d vtA %d vtS %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p), data_size, l_rlc_p->nb_sdu, l_rlc_p->current_sdu_index, l_rlc_p->next_sdu_index, conf, - mui); + mui, + l_rlc_p->vt_a, + l_rlc_p->vt_s); + } } else { #if MESSAGE_CHART_GENERATOR mui = ((struct rlc_am_data_req*) (sdu_pP->data))->mui; @@ -1279,12 +1280,14 @@ rlc_am_data_req ( data_size, mui); #endif - LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ BUFFER FULL, NB SDU %d current_sdu_index=%d next_sdu_index=%d size_input_sdus_buffer=%d\n", + LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ BUFFER FULL, NB SDU %d current_sdu_index=%d next_sdu_index=%d size_input_sdus_buffer=%d vtA=%d vtS=%d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p), l_rlc_p->nb_sdu, l_rlc_p->current_sdu_index, l_rlc_p->next_sdu_index, - RLC_AM_SDU_CONTROL_BUFFER_SIZE); + RLC_AM_SDU_CONTROL_BUFFER_SIZE, + l_rlc_p->vt_a, + l_rlc_p->vt_s); LOG_W(RLC, " input_sdus[].mem_block=%p next input_sdus[].flags.segmented=%d\n", l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mem_block, l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.segmented); l_rlc_p->stat_tx_pdcp_sdu_discarded += 1; diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h index 61c6a043cc0ba424571e2cba9d662461802563b6..4619a07315fa67cc6d6836a5b125c2ba208e0960 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h @@ -267,23 +267,32 @@ private_rlc_am( void rlc_am_get_pdus (const protocol_ctxt_t* const ctxtP,v */ protected_rlc_am( void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind);) -/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP) +/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC AM protocol instance pointer. * \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. +* \param[in] enb_flagP eNB or UE flag indication. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ -public_rlc_am( struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);) +public_rlc_am( struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP);) -/*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP) +/*! \fn void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP) +* \brief Set available TBS for RLC Tx just before am_mac_data_request. Used for UE only. +* \param[in] rlc_pP RLC AM protocol instance pointer. +* \param[in] tb_sizeP Available Tx Transport Block size in bytes. +*/ +public_rlc_am( void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP);) + +/*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP,const eNB_flag_t enb_flagP) * \brief Gives PDUs to lower layer MAC. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC AM protocol instance pointer. +* \param[in] enb_flagP eNB or UE flag * \return A PDU of the previously requested number of bytes, and the updated maximum number of bytes that can be served by RLC instance to MAC for next RLC transmission. */ -public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP);) +public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP,const eNB_flag_t enb_flagP);) /*! \fn void rlc_am_mac_data_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indP) * \brief Receive PDUs from lower layer MAC. @@ -293,6 +302,13 @@ public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ct */ public_rlc_am( void rlc_am_mac_data_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indP);) +/*! \fn uint32_t rlc_am_get_buffer_occupancy_in_bytes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP) +* \brief Get Tx Buffer Occupancy. +* \param[in] ctxt_pP Running context. +* \param[in] rlc_pP RLC AM protocol instance pointer. +*/ +public_rlc_am( uint32_t rlc_am_get_buffer_occupancy_in_bytes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP);) + /*! \fn void rlc_am_data_req (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, mem_block_t *sduP) * \brief Interface with higher layers, buffer higher layer SDUS for transmission. * \param[in] ctxt_pP Running context. diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_constants.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_constants.h index dcc5f2de8fe511da69b6b57d641db400d1033bf3..12af0279a8143fcd966f72c4b4d83e6f92b1fc12 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_constants.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_constants.h @@ -48,19 +48,22 @@ # define RLC_AM_SDU_DATA_BUFFER_SIZE 64*1024 /** Max number of incoming SDUs from upper layer that can be buffered in a RLC AM protocol instance. */ -# define RLC_AM_SDU_CONTROL_BUFFER_SIZE 128 +# define RLC_AM_SDU_CONTROL_BUFFER_SIZE 1024 /** Size of the retransmission buffer (number of PDUs). */ -# define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_SN_MODULO +# define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_WINDOW_SIZE /** PDU minimal header size in bytes. */ # define RLC_AM_HEADER_MIN_SIZE 2 +/** PDU Segment minimal header size in bytes = PDU header + SOStart + SOEnd. */ +# define RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE 4 + /** If we want to send a segment of a PDU, then the min transport block size requested by MAC should be this amount. */ # define RLC_AM_MIN_SEGMENT_SIZE_REQUEST 8 /** Max SDUs that can fit in a PDU. */ -# define RLC_AM_MAX_SDU_IN_PDU 32 +# define RLC_AM_MAX_SDU_IN_PDU 128 /** Max fragments for a SDU. */ # define RLC_AM_MAX_SDU_FRAGMENTS 32 @@ -69,6 +72,99 @@ # define RLC_AM_MAX_NACK_IN_STATUS_PDU 1023 /** Max holes created by NACK_SN with segment offsets for a PDU in the retransmission buffer. */ -# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 32 +# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 16 /** @} */ -# endif + +#define RLC_AM_POLL_PDU_INFINITE 0xFFFF +#define RLC_AM_POLL_BYTE_INFINITE 0xFFFFFFFF + +/* MACRO DEFINITIONS */ + +#define RLC_AM_NEXT_SN(sn) (((sn)+1) & (RLC_AM_SN_MASK)) +#define RLC_AM_PREV_SN(sn) (((sn)+(RLC_AM_SN_MODULO)-1) & (RLC_AM_SN_MASK)) + +#define RLC_DIFF_SN(sn,snref,modulus) ((sn+(modulus)-snref) & ((modulus)-1)) +#define RLC_SN_IN_WINDOW(sn,snref,modulus) ((RLC_DIFF_SN(sn,snref,modulus)) < ((modulus) >> 1)) + +#define RLC_AM_DIFF_SN(sn,snref) (RLC_DIFF_SN(sn,snref,RLC_AM_SN_MODULO)) +#define RLC_AM_SN_IN_WINDOW(sn,snref) (RLC_SN_IN_WINDOW(sn,snref,RLC_AM_SN_MODULO)) + +#define RLC_SET_BIT(x,offset) ((x) |= (1 << (offset))) +#define RLC_GET_BIT(x,offset) (((x) & (1 << (offset))) >> (offset)) +#define RLC_CLEAR_BIT(x,offset) ((x) &= ~(1 << (offset))) + +#define RLC_SET_EVENT(x,event) ((x) |= (event)) +#define RLC_GET_EVENT(x,event) ((x) & (event)) +#define RLC_CLEAR_EVENT(x,event) ((x) &= (~(event))) + +/* Common to Data and Status PDU */ +#define RLC_AM_SN_BITS 10 +#define RLC_AM_PDU_D_C_BITS 1 +#define RLC_AM_PDU_E_BITS 1 +#define RLC_AM_PDU_FI_BITS 2 +#define RLC_AM_PDU_POLL_BITS 1 +#define RLC_AM_PDU_RF_BITS 1 + + +#define RLC_AM_LI_BITS 11 +#define RLC_AM_LI_MASK 0x7FF + + +/* AM Data PDU */ +#define RLC_AM_PDU_E_OFFSET 2 +#define RLC_AM_PDU_FI_OFFSET (RLC_AM_PDU_E_OFFSET + RLC_AM_PDU_E_BITS) +#define RLC_AM_PDU_POLL_OFFSET (RLC_AM_PDU_FI_OFFSET + RLC_AM_PDU_FI_BITS) +#define RLC_AM_PDU_RF_OFFSET (RLC_AM_PDU_POLL_OFFSET + RLC_AM_PDU_POLL_BITS) +#define RLC_AM_PDU_D_C_OFFSET (RLC_AM_PDU_RF_OFFSET + RLC_AM_PDU_RF_BITS) + +#define RLC_AM_PDU_GET_FI_START(px) (RLC_GET_BIT((px),RLC_AM_PDU_FI_OFFSET + 1)) +#define RLC_AM_PDU_GET_FI_END(px) (RLC_GET_BIT((px),RLC_AM_PDU_FI_OFFSET)) + +#define RLC_AM_PDU_GET_LI(x,offset) (((x) >> (offset)) & RLC_AM_LI_MASK) +#define RLC_AM_PDU_SET_LI(x,li,offset) ((x) |= (((li) & RLC_AM_LI_MASK) << (offset))) + +#define RLC_AM_PDU_SET_E(px) (RLC_SET_BIT((px),RLC_AM_PDU_E_OFFSET)) +#define RLC_AM_PDU_SET_D_C(px) (RLC_SET_BIT((px),RLC_AM_PDU_D_C_OFFSET)) +#define RLC_AM_PDU_SET_RF(px) (RLC_SET_BIT((px),RLC_AM_PDU_RF_OFFSET)) +#define RLC_AM_PDU_SET_POLL(px) (RLC_SET_BIT((px),RLC_AM_PDU_POLL_OFFSET)) +#define RLC_AM_PDU_CLEAR_POLL(px) (RLC_CLEAR_BIT((px),RLC_AM_PDU_POLL_OFFSET)) + +#define RLC_AM_PDU_SEGMENT_SO_LENGTH 15 +#define RLC_AM_PDU_SEGMENT_SO_BYTES 2 +#define RLC_AM_PDU_SEGMENT_SO_OFFSET 0 +#define RLC_AM_PDU_LSF_OFFSET (RLC_AM_PDU_SEGMENT_SO_OFFSET + RLC_AM_PDU_SEGMENT_SO_LENGTH) + +#define RLC_AM_PDU_SET_LSF(px) (RLC_SET_BIT((px),RLC_AM_PDU_LSF_OFFSET)) + +#define RLC_AM_HEADER_LI_LENGTH(li) ((li) + ((li)>>1) + ((li)&1)) +#define RLC_AM_PDU_SEGMENT_HEADER_SIZE(numLis) (RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + RLC_AM_HEADER_LI_LENGTH(numLis)) + +/* STATUS PDU */ +#define RLC_AM_STATUS_PDU_CPT_STATUS 0 + +#define RLC_AM_STATUS_PDU_CPT_OFFSET 4 +#define RLC_AM_STATUS_PDU_CPT_LENGTH 3 + +#define RLC_AM_STATUS_PDU_ACK_SN_OFFSET 2 + +#define RLC_AM_STATUS_PDU_SO_LENGTH 15 + +#define RLC_AM_STATUS_PDU_SO_END_ALL_BYTES 0x7FFF + + +/* Uplink STATUS PDU trigger events */ +#define RLC_AM_STATUS_NOT_TRIGGERED 0 +#define RLC_AM_STATUS_TRIGGERED_POLL 0x01 /* Status Report is triggered by a received poll */ +#define RLC_AM_STATUS_TRIGGERED_T_REORDERING 0x02 /* Status Report is triggered by Timer Reordering Expiry */ +#define RLC_AM_STATUS_TRIGGERED_DELAYED 0x10 /* Status is delayed until SN(receivedPoll) < VR(MS) */ +#define RLC_AM_STATUS_PROHIBIT 0x20 /* TimerStatusProhibit still running */ +#define RLC_AM_STATUS_NO_TX_MASK (RLC_AM_STATUS_PROHIBIT | RLC_AM_STATUS_TRIGGERED_DELAYED) + +/* Status triggered (bit 5-7) will be concatenated with Poll triggered (bit 0-4) for RLCdec. RLC_AM_STATUS_TRIGGERED_DELAYED is not recorded. */ +#define RLC_AM_SET_STATUS(x,event) (RLC_SET_EVENT(x,event)) +#define RLC_AM_GET_STATUS(x,event) (RLC_GET_EVENT(x,event)) +#define RLC_AM_CLEAR_STATUS(x,event) (RLC_CLEAR_EVENT(x,event)) +#define RLC_AM_CLEAR_ALL_STATUS(x) ((x) = (RLC_AM_STATUS_NOT_TRIGGERED)) + + +#endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h index 42114d42691d20659f7d255c5781a885513651a6..602e8e98c2f7ff1bc3abef94b3ba07c1fe8fe45c 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h @@ -57,7 +57,6 @@ typedef struct rlc_am_entity_s { boolean_t is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ rlc_buffer_occupancy_t sdu_buffer_occupancy; /*!< \brief Number of bytes of unsegmented SDUs. */ - rlc_buffer_occupancy_t retransmission_buffer_occupancy; /*!< \brief Number of bytes of PDUs in retransmission buffer waiting for a ACK. */ rlc_buffer_occupancy_t status_buffer_occupancy; /*!< \brief Number of bytes of control PDUs waiting for transmission. */ rlc_am_control_pdu_info_t control_pdu_info; @@ -69,17 +68,14 @@ typedef struct rlc_am_entity_s { pthread_mutex_t lock_input_sdus; rlc_am_tx_sdu_management_t *input_sdus; /*!< \brief Input SDU buffer (for SDUs coming from upper layers). */ signed int nb_sdu; /*!< \brief Total number of valid rlc_am_tx_sdu_management_t in input_sdus[]. */ - signed int nb_sdu_no_segmented; /*!< \brief Total number of SDUs not segmented and partially segmented. */ + signed int nb_sdu_no_segmented; /*!< \brief Total number of SDUs not segmented and partially segmented. nb_sdu_no_segmented = next_sdu_index - current_sdu_index */ signed int next_sdu_index; /*!< \brief Next SDU index in input_sdus array where for a new incoming SDU. */ - signed int current_sdu_index; /*!< \brief Current SDU index in input_sdus array to be segmented. */ + signed int current_sdu_index; /*!< \brief Current SDU index in input_sdus array to be segmented which is not segmented or partially segmented. */ - rlc_am_tx_data_pdu_management_t *pdu_retrans_buffer; /*!< \brief Retransmission buffer. */ + rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer; /*!< \brief Transmission PDU data buffer. Used also for retransmissions */ signed int retrans_num_pdus; /*!< \brief Number of PDUs in the retransmission buffer. */ - signed int retrans_num_bytes; /*!< \brief Number of bytes in the retransmission buffer. */ - signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. */ - unsigned int num_nack_so; /*!< \brief Number of segment offsets asked to be retransmitted by peer RLC entity. */ - unsigned int num_nack_sn; /*!< \brief Number of segment asked to be retransmitted by peer RLC entity. */ + signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. Only payload is taken into account */ boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */ //--------------------------------------------------------------------- @@ -137,7 +133,7 @@ typedef struct rlc_am_entity_s { //----------------------------- uint16_t max_retx_threshold; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to limit the number of retransmissions of an AMD PDU. */ uint16_t poll_pdu; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollPDU PDUs. */ - uint16_t poll_byte; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollByte bytes. */ + uint32_t poll_byte; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollByte bytes. */ //--------------------------------------------------------------------- // STATISTICS @@ -176,14 +172,14 @@ typedef struct rlc_am_entity_s { //--------------------------------------------------------------------- // OUTPUTS //--------------------------------------------------------------------- - sdu_size_t nb_bytes_requested_by_mac; /*!< \brief Number of bytes requested by lower layer for next transmission. */ + sdu_size_t nb_bytes_requested_by_mac; /*!< \brief Number of remaining bytes available for transmission of any RLC PDU indicated by lower layer */ list_t pdus_to_mac_layer; /*!< \brief PDUs buffered for transmission to MAC layer. */ list_t control_pdu_list; /*!< \brief Control PDUs buffered for transmission to MAC layer. */ - rlc_sn_t first_retrans_pdu_sn; /*!< \brief Lowest sequence number of PDU to be retransmitted. */ list_t segmentation_pdu_list; /*!< \brief List of "freshly" segmented PDUs. */ - boolean_t status_requested; /*!< \brief Status requested by peer. */ - frame_t last_frame_status_indication; /*!< \brief The last frame number a MAC status indication has been received by RLC. */ + uint8_t status_requested; /*!< \brief Status bitmap requested by peer. */ + rlc_sn_t sn_status_triggered_delayed; /*!< \brief SN of the last received poll for which Status is delayed until SN is out of Rx Window. */ + uint32_t last_absolute_subframe_status_indication; /*!< \brief The last absolute subframe number a MAC status indication has been received by RLC. */ //----------------------------- // buffer occupancy measurements sent to MAC //----------------------------- diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.c index 0f0b0e75e1b70f24862309c86ac5c48ccfe5bde0..4b5c173d4b6e891c5d98b7eb7c1d95ade8e60719 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.c @@ -41,21 +41,28 @@ void rlc_am_free_in_sdu( const unsigned int index_in_bufferP) { if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) { + /* BugFix: SDU shall have been already freed during initial PDU segmentation or concatenation !! */ + AssertFatal(rlcP->input_sdus[index_in_bufferP].mem_block == NULL, "RLC AM Tx SDU Conf: Data Part is not empty index=%d LcId=%d\n", + index_in_bufferP,rlcP->channel_id); + /* if (rlcP->input_sdus[index_in_bufferP].mem_block != NULL) { free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__); rlcP->input_sdus[index_in_bufferP].mem_block = NULL; rlcP->nb_sdu_no_segmented -= 1; rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0; } + */ rlcP->nb_sdu -= 1; memset(&rlcP->input_sdus[index_in_bufferP], 0, sizeof(rlc_am_tx_sdu_management_t)); rlcP->input_sdus[index_in_bufferP].flags.transmitted_successfully = 1; + // case when either one SDU needs to be removed from segmentation or SDU buffer is full if (rlcP->current_sdu_index == index_in_bufferP) { rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE; } + // wrapping and reset current_sdu_index to next_sdu_index when all transmitted SDUs have been acknowledged while ((rlcP->current_sdu_index != rlcP->next_sdu_index) && (rlcP->input_sdus[rlcP->current_sdu_index].flags.transmitted_successfully == 1)) { rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE; @@ -100,3 +107,41 @@ rlc_am_in_sdu_is_empty( return 0; } + +// called when PDU is ACKED +//----------------------------------------------------------------------------- +void +rlc_am_pdu_sdu_data_cnf( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t* const rlc_pP, + const rlc_sn_t snP) +{ + int pdu_sdu_index; + int sdu_index; + + for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].nb_sdus; pdu_sdu_index++) { + sdu_index = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].sdus_index[pdu_sdu_index]; + assert(sdu_index >= 0); + assert(sdu_index < RLC_AM_SDU_CONTROL_BUFFER_SIZE); + rlc_pP->input_sdus[sdu_index].nb_pdus_ack += 1; + + if ((rlc_pP->input_sdus[sdu_index].nb_pdus_ack == rlc_pP->input_sdus[sdu_index].nb_pdus) && + (rlc_pP->input_sdus[sdu_index].sdu_remaining_size == 0)) { + #if TEST_RLC_AM + rlc_am_v9_3_0_test_data_conf ( + rlc_pP->module_id, + rlc_pP->rb_id, + rlc_pP->input_sdus[sdu_index].mui, + RLC_SDU_CONFIRM_YES); + #else + rlc_data_conf( + ctxt_pP, + rlc_pP->rb_id, + rlc_pP->input_sdus[sdu_index].mui, + RLC_SDU_CONFIRM_YES, + rlc_pP->is_data_plane); + #endif + rlc_am_free_in_sdu(ctxt_pP, rlc_pP, sdu_index); + } + } +} diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.h index 3201dfc94169374cf9c508f9ec9f9adbe1ec007b..c596bc671accf0c97b013c0342a6b7a21675d0d6 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_in_sdu.h @@ -77,5 +77,13 @@ protected_rlc_am_in_sdu(void rlc_am_free_in_sdu_data (const protocol_ctxt_t* con * \return 1 if the buffer is empty, else 0. */ protected_rlc_am_in_sdu(signed int rlc_am_in_sdu_is_empty(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP);) + +/*! \fn void rlc_am_pdu_sdu_data_cnf(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,const rlc_sn_t snP) +* \brief Process SDU cnf of a ACKED PDU for all SDUs concatenated in this PDU. +* \param[in] ctxtP Running context. +* \param[in] rlcP RLC AM protocol instance pointer. +* \param[in] snP Sequence number of the PDU. +*/ +protected_rlc_am_in_sdu(void rlc_am_pdu_sdu_data_cnf(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,const rlc_sn_t snP);) /** @} */ # endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c index cb03e28c4b457d8e9ce39344dbe32213f5d3bb26..129d4ffb0f97f621cc3d17898006a17082c39a5d 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c @@ -51,16 +51,16 @@ rlc_am_init( pthread_mutex_init(&rlc_pP->lock_input_sdus, NULL); rlc_pP->input_sdus = calloc(1, RLC_AM_SDU_CONTROL_BUFFER_SIZE*sizeof(rlc_am_tx_sdu_management_t)); //#warning "cast the rlc retrans buffer to uint32" - // rlc_pP->pdu_retrans_buffer = calloc(1, (uint16_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t))); - rlc_pP->pdu_retrans_buffer = calloc(1, (uint32_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof( + // rlc_pP->tx_data_pdu_buffer = calloc(1, (uint16_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t))); + rlc_pP->tx_data_pdu_buffer = calloc(1, (uint32_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof( rlc_am_tx_data_pdu_management_t))); LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] input_sdus[] = %p element size=%zu\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->input_sdus, sizeof(rlc_am_tx_sdu_management_t)); - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] pdu_retrans_buffer[] = %p element size=%zu\n", + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] tx_data_pdu_buffer[] = %p element size=%zu\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->pdu_retrans_buffer, + rlc_pP->tx_data_pdu_buffer, sizeof(rlc_am_tx_data_pdu_management_t)); // TX state variables @@ -74,12 +74,12 @@ rlc_am_init( // RX state variables //rlc_pP->vr_r = 0; rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE; - //rlc_pP->vr_x = 0; + rlc_pP->vr_x = RLC_SN_UNDEFINED; //rlc_pP->vr_ms = 0; //rlc_pP->vr_h = 0; + rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; - rlc_pP->last_frame_status_indication = 123456; // any value > 1 - rlc_pP->first_retrans_pdu_sn = -1; + rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1 rlc_pP->initialized = TRUE; } @@ -128,12 +128,13 @@ rlc_am_reestablish( // RX state variables rlc_pP->vr_r = 0; rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE; - rlc_pP->vr_x = 0; + rlc_pP->vr_x = RLC_SN_UNDEFINED; rlc_pP->vr_ms = 0; rlc_pP->vr_h = 0; + rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; + rlc_pP->status_requested = RLC_AM_STATUS_NOT_TRIGGERED; - rlc_pP->last_frame_status_indication = 123456; // any value > 1 - rlc_pP->first_retrans_pdu_sn = -1; + rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1 rlc_pP->initialized = TRUE; @@ -172,16 +173,16 @@ rlc_am_cleanup( pthread_mutex_destroy(&rlc_pP->lock_input_sdus); - if (rlc_pP->pdu_retrans_buffer != NULL) { + if (rlc_pP->tx_data_pdu_buffer != NULL) { for (i=0; i < RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE; i++) { - if (rlc_pP->pdu_retrans_buffer[i].mem_block != NULL) { - free_mem_block(rlc_pP->pdu_retrans_buffer[i].mem_block, __func__); - rlc_pP->pdu_retrans_buffer[i].mem_block = NULL; + if (rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block != NULL) { + free_mem_block(rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block, __func__); + rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block = NULL; } } - free(rlc_pP->pdu_retrans_buffer); - rlc_pP->pdu_retrans_buffer = NULL; + free(rlc_pP->tx_data_pdu_buffer); + rlc_pP->tx_data_pdu_buffer = NULL; } memset(rlc_pP, 0, sizeof(rlc_am_entity_t)); diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c index 873e51fbfe395c0e6aa48909a11c46830d682a59..4202443a5a4e02c5248836e0607a61a9a5ce9bf7 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c @@ -91,7 +91,7 @@ rlc_am_send_sdu ( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP) { -# if TRACE_RLC_UM_PDU +# if TRACE_RLC_AM_PDU char message_string[7000]; size_t message_string_size = 0; #if ENABLE_ITTI @@ -212,7 +212,8 @@ void rlc_am_reassemble_pdu( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, - mem_block_t * const tb_pP) + mem_block_t * const tb_pP, + boolean_t free_rlc_pdu) { int i,j; @@ -397,5 +398,7 @@ rlc_am_reassemble_pdu( } } - free_mem_block(tb_pP, __func__); + if (free_rlc_pdu) { + free_mem_block(tb_pP, __func__); + } } diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h index fece9ae5709c9ecfae4dd718b736f032192e3a25..4b780ce4414c2735074a4477b93fbf3e58c5e5e9 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h @@ -72,13 +72,14 @@ private_rlc_am_reassembly( void rlc_am_reassembly (const protocol_ctxt_t* co */ private_rlc_am_reassembly( void rlc_am_send_sdu (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP);) -/*! \fn void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const mem_block_t* const tb_pP) +/*! \fn void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const mem_block_t* const tb_pP,boolean_t free_rlc_pdu) * \brief Reassembly a RLC AM PDU, depending of the content of this PDU, data will be reassemblied to the current output SDU, the current will be sent to higher layers or not, after or before the reassembly, or no send of SDU will be triggered, depending on FI field in PDU header. * \param[in] ctxtP Running context. * \param[in] rlc_pP RLC AM protocol instance pointer. * \param[in] tb_pP RLC AM PDU embedded in a mem_block_t. +* \param[in] free_rlc_pdu Flag for freeing RLC AM PDU after reassembly. */ -protected_rlc_am_reassembly( void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, mem_block_t* const tb_pP);) +protected_rlc_am_reassembly( void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, mem_block_t* const tb_pP,boolean_t free_rlc_pdu);) /** @} */ #endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c index d783684893565fa74cf32aef762d604823d706a9..d2a5cc985e848881c26fda350b996a6e5bb5485e 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c @@ -31,6 +31,7 @@ #include "LAYER2/MAC/extern.h" #include "UTIL/LOG/log.h" + //----------------------------------------------------------------------------- signed int rlc_am_get_data_pdu_infos( @@ -40,14 +41,15 @@ rlc_am_get_data_pdu_infos( int16_t total_sizeP, rlc_am_pdu_info_t* pdu_info_pP) { - memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t)); + memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t)); - int16_t sum_li = 0; - pdu_info_pP->d_c = header_pP->b1 >> 7; - pdu_info_pP->num_li = 0; + int16_t sum_li = 0; + pdu_info_pP->d_c = header_pP->b1 >> 7; + pdu_info_pP->num_li = 0; - if (pdu_info_pP->d_c) { + AssertFatal (pdu_info_pP->d_c != 0, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id); + pdu_info_pP->rf = (header_pP->b1 >> 6) & 0x01; pdu_info_pP->p = (header_pP->b1 >> 5) & 0x01; pdu_info_pP->fi = (header_pP->b1 >> 3) & 0x03; @@ -117,12 +119,6 @@ rlc_am_get_data_pdu_infos( } return 0; - } else { - LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[GET DATA PDU INFO] SN %04d ERROR CONTROL PDU ", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - pdu_info_pP->sn); - return -1; - } } //----------------------------------------------------------------------------- void @@ -181,26 +177,22 @@ rlc_am_rx_update_vr_ms( do { pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; - if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) { + if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) || + (rlc_pP->vr_ms != pdu_info_cursor_p->sn)) { + #if TRACE_RLC_AM_RX LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->vr_ms, pdu_info_cursor_p->sn); #endif - rlc_pP->vr_ms = pdu_info_cursor_p->sn; + return; } + rlc_pP->vr_ms = RLC_AM_NEXT_SN(pdu_info_cursor_p->sn); cursor_p = cursor_p->next; - } while (cursor_p != NULL); + } while ((cursor_p != NULL) && (rlc_pP->vr_ms != rlc_pP->vr_h)); -#if TRACE_RLC_AM_RX - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->vr_ms, - (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK); -#endif - rlc_pP->vr_ms = (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK; } } // assumed the sn of the tb_p is equal to VR(R) @@ -322,34 +314,30 @@ rlc_am_receive_process_data_pdu ( // - discard the duplicate byte segments. rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info; rlc_am_pdu_sn_10_t* rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)first_byte_pP; + rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK; + boolean_t reassemble = false; if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_pP, rlc_am_pdu_sn_10_p, tb_size_in_bytesP, pdu_info_p) >= 0) { ((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received = 0; - if (rlc_am_in_rx_window(ctxt_pP, rlc_pP, pdu_info_p->sn)) { - - if (pdu_info_p->p) { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] POLL BIT SET, STATUS REQUESTED:\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); - rlc_pP->status_requested = 1; - } + if (RLC_AM_SN_IN_WINDOW(pdu_info_p->sn, rlc_pP->vr_r)) { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] VR(R) %04d VR(H) %04d VR(MR) %04d VR(MS) %04d VR(X) %04d\n", + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] VR(R) %04d VR(H) %04d VR(MR) %04d VR(MS) %04d VR(X) %04d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + pdu_info_p->sn, rlc_pP->vr_r, rlc_pP->vr_h, rlc_pP->vr_mr, rlc_pP->vr_ms, rlc_pP->vr_x); - if (rlc_am_rx_list_insert_pdu(ctxt_pP, rlc_pP,tb_pP) < 0) { + pdu_status = rlc_am_rx_list_check_duplicate_insert_pdu(ctxt_pP, rlc_pP,tb_pP); + if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) { rlc_pP->stat_rx_data_pdu_dropped += 1; rlc_pP->stat_rx_data_bytes_dropped += tb_size_in_bytesP; - free_mem_block (tb_pP, __func__); - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED, STATUS REQUESTED:\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); - rlc_pP->status_requested = 1; + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED CAUSE=%d SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_status,pdu_info_p->sn); #if RLC_STOP_ON_LOST_PDU AssertFatal( 0 == 1, PROTOCOL_RLC_AM_CTXT_FMT" LOST PDU DETECTED\n", @@ -394,12 +382,15 @@ rlc_am_receive_process_data_pdu ( rlc_am_rx_list_display(rlc_pP, "rlc_am_receive_process_data_pdu AFTER INSERTION "); #endif - if (rlc_am_sn_gte_vr_h(ctxt_pP, rlc_pP, pdu_info_p->sn) > 0) { - rlc_pP->vr_h = (pdu_info_p->sn + 1) & RLC_AM_SN_MASK; + /* 1) Update vrH if sn >= vrH */ + if (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(rlc_pP->vr_h,rlc_pP->vr_r)) + { + rlc_pP->vr_h = RLC_AM_NEXT_SN(pdu_info_p->sn); } rlc_am_rx_check_all_byte_segments(ctxt_pP, rlc_pP, tb_pP); + /* 2) Reordering Window Processing: Update vr_ms if sn = vr_ms and all bytes received for sn */ if ((pdu_info_p->sn == rlc_pP->vr_ms) && (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received)) { rlc_am_rx_update_vr_ms(ctxt_pP, rlc_pP, tb_pP); } @@ -410,39 +401,114 @@ rlc_am_receive_process_data_pdu ( rlc_pP->vr_mr = (rlc_pP->vr_r + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK; } - rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP); + reassemble = rlc_am_rx_check_vr_reassemble(ctxt_pP, rlc_pP); + //TODO : optimization : check whether a reassembly is needed by looking at LI, FI, SO, etc... + } //FNA: fix check VrX out of receiving window - if (rlc_pP->t_reordering.running) { - if ((rlc_pP->vr_x == rlc_pP->vr_r) || ((rlc_am_in_rx_window(ctxt_pP, rlc_pP, rlc_pP->vr_x) == 0) && (rlc_pP->vr_x != rlc_pP->vr_mr))) { + if ((rlc_pP->t_reordering.running) || ((rlc_pP->t_reordering.ms_duration == 0) && (rlc_pP->vr_x != RLC_SN_UNDEFINED))) { + if ((rlc_pP->vr_x == rlc_pP->vr_r) || (!(RLC_AM_SN_IN_WINDOW(rlc_pP->vr_x, rlc_pP->vr_r)) && (rlc_pP->vr_x != rlc_pP->vr_mr))) { rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP); + rlc_pP->vr_x = RLC_SN_UNDEFINED; } } if (!(rlc_pP->t_reordering.running)) { if (rlc_pP->vr_h != rlc_pP->vr_r) { // - if VR (H) > VR(R) translated to - if VR (H) != VR(R) - rlc_am_start_timer_reordering(ctxt_pP, rlc_pP); rlc_pP->vr_x = rlc_pP->vr_h; + if (rlc_pP->t_reordering.ms_duration != 0) { + rlc_am_start_timer_reordering(ctxt_pP, rlc_pP); + } + else { + /* specific case for no timer reordering configured */ + /* reordering window directly advances with vrH */ + rlc_pP->vr_ms = rlc_pP->vr_h; + + /* Trigger a Status and clear any existing Delay Flag */ + RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING); + RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED); + rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; + } } } } - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] VR(R) %04d VR(H) %04d VR(MS) %04d VR(MR) %04d\n", + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] NEW VR(R) %04d VR(H) %04d VR(MS) %04d VR(MR) %04d VR(X) %04d reassemble=%d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + pdu_info_p->sn, rlc_pP->vr_r, rlc_pP->vr_h, rlc_pP->vr_ms, - rlc_pP->vr_mr); + rlc_pP->vr_mr, + rlc_pP->vr_x, + reassemble); } else { rlc_pP->stat_rx_data_pdu_out_of_window += 1; rlc_pP->stat_rx_data_bytes_out_of_window += tb_size_in_bytesP; - free_mem_block (tb_pP, __func__); - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU OUT OF RX WINDOW, DISCARDED, STATUS REQUESTED:\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); - rlc_pP->status_requested = 1; + pdu_status = RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW; + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU OUT OF RX WINDOW, DISCARDED, SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn); } + + /* 3) Check for triggering a Tx Status PDU if a poll is received or if a pending status was delayed */ + if ((pdu_info_p->p) && (pdu_status < RLC_AM_DATA_PDU_STATUS_BUFFER_FULL)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] POLL BIT SET, STATUS REQUESTED:\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); + + /* Polling Info Saving for In and Out of Window PDU */ + /* avoid multi status trigger */ + if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) || + !(RLC_AM_GET_STATUS(rlc_pP->status_requested,(RLC_AM_STATUS_TRIGGERED_POLL | RLC_AM_STATUS_TRIGGERED_T_REORDERING)))) + { + RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_POLL); + + if ((pdu_status != RLC_AM_DATA_PDU_STATUS_OK) || ((pdu_status == RLC_AM_DATA_PDU_STATUS_OK) && + (!(RLC_AM_SN_IN_WINDOW(pdu_info_p->sn,rlc_pP->vr_r)) || + (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))) + ) + ) + { + /* Conditions are met for sending a Status Report */ + /* Then clear Delay Flag and reset its corresponding sn */ + RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED); + rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; + } + else if (rlc_pP->sn_status_triggered_delayed == RLC_SN_UNDEFINED) + { + /* Delay status trigger if pdustatus OK and sn>= vr_ms */ + /* Note: vr_r and vr_ms have been updated */ + RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED); + rlc_pP->sn_status_triggered_delayed = pdu_info_p->sn; + } + } + } + + /* ReEnable a previously delayed Status Trigger if PDU discarded or */ + /* sn no more in RxWindow due to RxWindow advance or sn < vr_ms */ + if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) && + (pdu_status == RLC_AM_DATA_PDU_STATUS_OK) && + (!(RLC_AM_SN_IN_WINDOW(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r)) || + (RLC_AM_DIFF_SN(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))) + ) + { + RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED); + rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; + } + + } else { - free_mem_block (tb_pP, __func__); + pdu_status = RLC_AM_DATA_PDU_STATUS_HEADER_ERROR; + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED BAD HEADER FORMAT SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn); + } + + if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) { + /* Discard received block if out of window, duplicate or header error */ + free_mem_block (tb_pP, __func__); + } + else if (reassemble) { + /* Reassemble SDUs */ + rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP); } } diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c index 7fb801b33d717c6d686c2eb8985a07399c7d71a5..f80a46695d21baef203f4eaa59ec03b8267358ae 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c @@ -30,12 +30,13 @@ #include "UTIL/LOG/log.h" #include "msc.h" //----------------------------------------------------------------------------- -void rlc_am_nack_pdu ( +boolean_t rlc_am_nack_pdu ( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlc_pP, const rlc_sn_t snP, - const sdu_size_t so_startP, - const sdu_size_t so_endP) + const rlc_sn_t prev_nack_snP, + sdu_size_t so_startP, + sdu_size_t so_endP) { // 5.2.1 Retransmission // ... @@ -50,55 +51,124 @@ void rlc_am_nack_pdu ( // - indicate to upper layers that max retransmission has been reached. - mem_block_t* mb_p = rlc_pP->pdu_retrans_buffer[snP].mem_block; - int pdu_sdu_index; - int sdu_index; + mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block; + rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE]; + //int pdu_sdu_index; + //int sdu_index; + boolean_t status = TRUE; + boolean_t retx_count_increment = FALSE; + sdu_size_t pdu_data_to_retx = 0; if (mb_p != NULL) { - rlc_pP->num_nack_sn += 1; assert(so_startP <= so_endP); - //----------------------------------------- - // allow holes in reports - // it is assumed that hole reports are done in byte offset - // increasing order among calls refering to only one status PDU - // and among time - //----------------------------------------- - if (rlc_pP->pdu_retrans_buffer[snP].last_nack_time != ctxt_pP->frame) { - rlc_pP->pdu_retrans_buffer[snP].last_nack_time = ctxt_pP->frame; - rlc_am_clear_holes(ctxt_pP, rlc_pP, snP); - } + // Handle full PDU NACK first + if ((so_startP == 0) && (so_endP == 0x7FFF)) { + if ((prev_nack_snP != snP) && (tx_data_pdu_buffer_p->flags.ack == 0) && (tx_data_pdu_buffer_p->flags.max_retransmit == 0)) { + pdu_data_to_retx = tx_data_pdu_buffer_p->payload_size; + /* Increment VtReTxNext if this is the first NACK or if some segments have already been transmitted */ + if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (tx_data_pdu_buffer_p->nack_so_start)) + { + retx_count_increment = TRUE; + } - if (!((so_startP == 0) && (so_endP == 0x7FFF))) { - rlc_pP->num_nack_so += 1; + tx_data_pdu_buffer_p->nack_so_start = 0; + tx_data_pdu_buffer_p->num_holes = 0; + tx_data_pdu_buffer_p->retx_hole_index = 0; + tx_data_pdu_buffer_p->nack_so_stop = tx_data_pdu_buffer_p->payload_size - 1; + #if TRACE_RLC_AM_HOLE + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] SN %04d GLOBAL NACK 0->%05d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + snP, + so_stopP); + #endif + assert(tx_data_pdu_buffer_p->nack_so_start < tx_data_pdu_buffer_p->payload_size); + } + else { + status = FALSE; + } + } + else if (tx_data_pdu_buffer_p->flags.max_retransmit == 0) { + // Handle Segment offset + if (so_endP == 0x7FFF) { + so_endP = tx_data_pdu_buffer_p->payload_size - 1; + } + + // Check consistency + if ((so_startP <= so_endP) && (so_endP < tx_data_pdu_buffer_p->payload_size)) { + if (prev_nack_snP != snP) { + /* New NACK_SN with SO */ + /* check whether a new segment is to be placed in Retransmission Buffer, then increment vrReTx */ + if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (so_startP < tx_data_pdu_buffer_p->nack_so_start)) { + retx_count_increment = TRUE; + } + + tx_data_pdu_buffer_p->num_holes = 1; + tx_data_pdu_buffer_p->retx_hole_index = 0; + tx_data_pdu_buffer_p->hole_so_start[0] = so_startP; + tx_data_pdu_buffer_p->hole_so_stop[0] = so_endP; + tx_data_pdu_buffer_p->nack_so_start = so_startP; + tx_data_pdu_buffer_p->nack_so_stop = so_endP; + pdu_data_to_retx = so_endP - so_startP + 1; + + } + else if ((tx_data_pdu_buffer_p->num_holes) && (tx_data_pdu_buffer_p->num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU)) { + /* New SOStart/SOEnd for the same NACK_SN than before */ + /* check discontinuity */ + if (so_startP > tx_data_pdu_buffer_p->hole_so_stop[tx_data_pdu_buffer_p->num_holes - 1]) { + tx_data_pdu_buffer_p->hole_so_start[tx_data_pdu_buffer_p->num_holes] = so_startP; + tx_data_pdu_buffer_p->hole_so_stop[tx_data_pdu_buffer_p->num_holes] = so_endP; + tx_data_pdu_buffer_p->nack_so_stop = so_endP; + tx_data_pdu_buffer_p->num_holes ++; + pdu_data_to_retx = so_endP - so_startP + 1; + } + else { + status = FALSE; + } + } + else { + status = FALSE; + } + } + else { + status = FALSE; + } } - - rlc_am_add_hole(ctxt_pP, rlc_pP, snP, so_startP, so_endP); - - if (rlc_pP->first_retrans_pdu_sn < 0) { - rlc_pP->first_retrans_pdu_sn = snP; - } else if (rlc_am_tx_sn1_gt_sn2(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn, snP)) { - rlc_pP->first_retrans_pdu_sn = snP; + else { + status = FALSE; } - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] NACK PDU SN %04d previous retx_count %d 1ST_RETRANS_PDU %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - snP, - rlc_pP->pdu_retrans_buffer[snP].retx_count, - rlc_pP->first_retrans_pdu_sn); - - rlc_pP->pdu_retrans_buffer[snP].flags.retransmit = 1; - - if (rlc_pP->pdu_retrans_buffer[snP].retx_count == -1) { - rlc_pP->pdu_retrans_buffer[snP].retx_count = 0; - rlc_pP->retrans_num_bytes_to_retransmit += rlc_pP->pdu_retrans_buffer[snP].header_and_payload_size; - } else { - rlc_pP->pdu_retrans_buffer[snP].retx_count += 1; + if (status) { + tx_data_pdu_buffer_p->flags.nack = 1; + if ((retx_count_increment) && (tx_data_pdu_buffer_p->retx_count == tx_data_pdu_buffer_p->retx_count_next)) { + tx_data_pdu_buffer_p->retx_count_next ++; + } + if (tx_data_pdu_buffer_p->flags.retransmit == 1) { + if (prev_nack_snP != snP) { + /* if first process of this NACK_SN and data already pending for retx */ + rlc_pP->retrans_num_bytes_to_retransmit += (pdu_data_to_retx - tx_data_pdu_buffer_p->retx_payload_size); + tx_data_pdu_buffer_p->retx_payload_size = pdu_data_to_retx; + } + else if (tx_data_pdu_buffer_p->num_holes > 1) { + /* Segment case : SOStart and SOEnd already received for same NACK_SN */ + /* filter case where a NACK_SN is received twice with SO first time and no SO second time */ + rlc_pP->retrans_num_bytes_to_retransmit += pdu_data_to_retx; + tx_data_pdu_buffer_p->retx_payload_size += pdu_data_to_retx; + } + } + else { + tx_data_pdu_buffer_p->flags.retransmit = 1; + rlc_pP->retrans_num_bytes_to_retransmit += pdu_data_to_retx; + tx_data_pdu_buffer_p->retx_payload_size = pdu_data_to_retx; + rlc_pP->retrans_num_pdus ++; + } } - if (rlc_pP->pdu_retrans_buffer[snP].retx_count >= rlc_pP->max_retx_threshold) { - for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->pdu_retrans_buffer[snP].nb_sdus; pdu_sdu_index++) { - sdu_index = rlc_pP->pdu_retrans_buffer[snP].sdus_index[pdu_sdu_index]; + /* TODO: Move this part in UL SCH processing */ +#if 0 + if (rlc_pP->tx_data_pdu_buffer[snP].retx_count >= rlc_pP->max_retx_threshold) { + for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->tx_data_pdu_buffer[snP].nb_sdus; pdu_sdu_index++) { + sdu_index = rlc_pP->tx_data_pdu_buffer[snP].sdus_index[pdu_sdu_index]; assert(pdu_sdu_index < RLC_AM_MAX_SDU_IN_PDU); assert(sdu_index < RLC_AM_SDU_CONTROL_BUFFER_SIZE); rlc_pP->input_sdus[sdu_index].nb_pdus_ack += 1; @@ -122,12 +192,15 @@ void rlc_am_nack_pdu ( } } } +#endif } else { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU SN %05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP); - //assert(2==3); + status = FALSE; } + + return status; } //----------------------------------------------------------------------------- void rlc_am_ack_pdu ( @@ -135,100 +208,27 @@ void rlc_am_ack_pdu ( rlc_am_entity_t *const rlc_pP, const rlc_sn_t snP) { - mem_block_t* mb_p = rlc_pP->pdu_retrans_buffer[snP].mem_block; - int pdu_sdu_index; - int sdu_index; + mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block; + rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE]; - rlc_pP->pdu_retrans_buffer[snP].flags.retransmit = 0; + tx_data_pdu_buffer->flags.retransmit = 0; - if ((rlc_pP->pdu_retrans_buffer[snP].flags.ack == 0) && (mb_p != NULL)) { + if ((tx_data_pdu_buffer->flags.ack == 0) && (mb_p != NULL)) { //if (mb_pP != NULL) { free_mem_block(mb_p, __func__); - rlc_pP->pdu_retrans_buffer[snP].mem_block = NULL; + tx_data_pdu_buffer->mem_block = NULL; LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] ACK PDU SN %05d previous retx_count %d \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, - rlc_pP->pdu_retrans_buffer[snP].retx_count); - rlc_pP->retrans_num_pdus -= 1; - rlc_pP->retrans_num_bytes -= rlc_pP->pdu_retrans_buffer[snP].header_and_payload_size; - - if (rlc_pP->pdu_retrans_buffer[snP].retx_count >= 0) { - rlc_pP->retrans_num_bytes_to_retransmit -= rlc_pP->pdu_retrans_buffer[snP].header_and_payload_size; - } - - for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->pdu_retrans_buffer[snP].nb_sdus; pdu_sdu_index++) { - sdu_index = rlc_pP->pdu_retrans_buffer[snP].sdus_index[pdu_sdu_index]; - assert(sdu_index >= 0); - assert(sdu_index < RLC_AM_SDU_CONTROL_BUFFER_SIZE); - rlc_pP->input_sdus[sdu_index].nb_pdus_ack += 1; + tx_data_pdu_buffer->retx_count); - if ((rlc_pP->input_sdus[sdu_index].nb_pdus_ack == rlc_pP->input_sdus[sdu_index].nb_pdus) && - (rlc_pP->input_sdus[sdu_index].sdu_remaining_size == 0)) { -#if TEST_RLC_AM - rlc_am_v9_3_0_test_data_conf ( - rlc_pP->module_id, - rlc_pP->rb_id, - rlc_pP->input_sdus[sdu_index].mui, - RLC_SDU_CONFIRM_YES); -#else - rlc_data_conf( - ctxt_pP, - rlc_pP->rb_id, - rlc_pP->input_sdus[sdu_index].mui, - RLC_SDU_CONFIRM_YES, - rlc_pP->is_data_plane); -#endif - rlc_am_free_in_sdu(ctxt_pP, rlc_pP, sdu_index); - } + if (tx_data_pdu_buffer->retx_payload_size) { + rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_buffer->retx_payload_size; + tx_data_pdu_buffer->retx_payload_size = 0; + tx_data_pdu_buffer->num_holes = 0; + rlc_pP->retrans_num_pdus --; } - // 7.1... - // VT(A) – Acknowledgement state variable - // This state variable holds the value of the SN of the next AMD PDU for which a positive acknowledgment is to be - // received in-sequence, and it serves as the lower edge of the transmitting window. It is initially set to 0, and is updated - // whenever the AM RLC entity receives a positive acknowledgment for an AMD PDU with SN = VT(A). - rlc_pP->pdu_retrans_buffer[snP].flags.ack = 1; - - if (snP == rlc_pP->vt_a) { - //rlc_pP->pdu_retrans_buffer[snP].flags.ack = 1; - do { - memset(&rlc_pP->pdu_retrans_buffer[rlc_pP->vt_a], 0, sizeof(rlc_am_tx_data_pdu_management_t)); - - if (rlc_pP->vt_a == rlc_pP->first_retrans_pdu_sn) { - rlc_pP->first_retrans_pdu_sn = (rlc_pP->vt_a + 1) & RLC_AM_SN_MASK; - } - - rlc_pP->vt_a = (rlc_pP->vt_a + 1) & RLC_AM_SN_MASK; - } while ((rlc_pP->pdu_retrans_buffer[rlc_pP->vt_a].flags.ack == 1) && (rlc_pP->vt_a != rlc_pP->vt_s)); - - - rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK; - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] UPDATED VT(A) %04d VT(MS) %04d VT(S) %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->vt_a, - rlc_pP->vt_ms, - rlc_pP->vt_s); - } - - if (snP == rlc_pP->first_retrans_pdu_sn) { - do { - rlc_pP->first_retrans_pdu_sn = (rlc_pP->first_retrans_pdu_sn + 1) & RLC_AM_SN_MASK; - - if (rlc_pP->pdu_retrans_buffer[rlc_pP->first_retrans_pdu_sn].retx_count >= 0) { - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] UPDATED first_retrans_pdu_sn -> %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn); - break; - } - } while (rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s); - - if (rlc_pP->vt_s == rlc_pP->first_retrans_pdu_sn) { - rlc_pP->first_retrans_pdu_sn = -1; - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] UPDATED first_retrans_pdu_sn -> %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->first_retrans_pdu_sn); - } - } } else { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] WARNING ACK PDU SN %05d -> NO PDU TO ACK\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), @@ -236,31 +236,13 @@ void rlc_am_ack_pdu ( if (mb_p != NULL) { free_mem_block(mb_p, __func__); - rlc_pP->pdu_retrans_buffer[snP].mem_block = NULL; - } - - if (rlc_pP->pdu_retrans_buffer[snP].flags.ack > 0) { - if (snP == rlc_pP->vt_a) { - //rlc_pP->pdu_retrans_buffer[snP].flags.ack = 1; - do { - memset(&rlc_pP->pdu_retrans_buffer[rlc_pP->vt_a], 0, sizeof(rlc_am_tx_data_pdu_management_t)); - - if (rlc_pP->vt_a == rlc_pP->first_retrans_pdu_sn) { - rlc_pP->first_retrans_pdu_sn = (rlc_pP->vt_a + 1) & RLC_AM_SN_MASK; - } - - rlc_pP->vt_a = (rlc_pP->vt_a + 1) & RLC_AM_SN_MASK; - } while ((rlc_pP->pdu_retrans_buffer[rlc_pP->vt_a].flags.ack == 1) && (rlc_pP->vt_a != rlc_pP->vt_s)); - - rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK; - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] UPDATED VT(A) %04d VT(MS) %04d VT(S) %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->vt_a, - rlc_pP->vt_ms, - rlc_pP->vt_s); - } + tx_data_pdu_buffer->mem_block = NULL; } } + tx_data_pdu_buffer->flags.ack = 1; + tx_data_pdu_buffer->flags.transmitted = 0; + tx_data_pdu_buffer->flags.retransmit = 0; + } //----------------------------------------------------------------------------- mem_block_t* rlc_am_retransmit_get_copy ( @@ -268,27 +250,414 @@ mem_block_t* rlc_am_retransmit_get_copy ( rlc_am_entity_t *const rlc_pP, const rlc_sn_t snP) { - mem_block_t* mb_original_p = rlc_pP->pdu_retrans_buffer[snP].mem_block; + mem_block_t* mb_original_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block; - if (mb_original_p != NULL) { + AssertFatal (mb_original_p != NULL, "RLC AM PDU Copy Error: Empty block sn=%d vtA=%d vtS=%d LcId=%d !\n", + snP,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); - rlc_am_tx_data_pdu_management_t *pdu_mngt = &rlc_pP->pdu_retrans_buffer[snP % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE]; + rlc_am_tx_data_pdu_management_t *pdu_mngt = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE]; - int size = pdu_mngt->header_and_payload_size + sizeof(struct mac_tb_req); - mem_block_t* mb_copy = get_free_mem_block(size, __func__); - memcpy(mb_copy->data, mb_original_p->data, size); + /* We need to allocate a new buffer and copy to it because header content may change for Polling bit */ + int size = pdu_mngt->header_and_payload_size + sizeof(struct mac_tb_req); + mem_block_t* mb_copy = get_free_mem_block(size, __func__); + memcpy(mb_copy->data, mb_original_p->data, size); - rlc_am_pdu_sn_10_t *pdu_p = (rlc_am_pdu_sn_10_t*) (&mb_copy->data[sizeof(struct mac_tb_req)]); - ((struct mac_tb_req*)(mb_copy->data))->data_ptr = (uint8_t*)pdu_p; + rlc_am_pdu_sn_10_t *pdu_p = (rlc_am_pdu_sn_10_t*) (&mb_copy->data[sizeof(struct mac_tb_req)]); + ((struct mac_tb_req*)(mb_copy->data))->data_ptr = (uint8_t*)pdu_p; - pdu_mngt->flags.retransmit = 0; + return mb_copy; +} - rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt->payload_size); - return mb_copy; - } else { - return NULL; - } +//----------------------------------------------------------------------------- +mem_block_t* rlc_am_retransmit_get_am_segment( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlc_pP, + rlc_am_tx_data_pdu_management_t *const pdu_mngt, + sdu_size_t * const payload_sizeP /* in-out*/) +{ + int16_t sdus_segment_size[RLC_AM_MAX_SDU_IN_PDU]; + mem_block_t* mb_original_p = pdu_mngt->mem_block; + mem_block_t* mem_pdu_segment_p = NULL; + uint8_t *pdu_original_header_p = NULL; + uint8_t *pdu_segment_header_p = NULL; + sdu_size_t retx_so_start,retx_so_stop; //starting and ending SO for retransmission in this PDU + rlc_sn_t sn = pdu_mngt->sn; + uint16_t header_so_part; + boolean_t fi_start, fi_end; + uint8_t sdu_index = 0; + uint8_t sdu_segment_index = 0; + uint8_t num_LIs_pdu_segment = pdu_mngt->nb_sdus - 1; + uint8_t li_bit_offset = 4; /* toggle between 0 and 4 */ + uint8_t li_jump_offset = 1; /* toggle between 1 and 2 */ + + + AssertFatal (mb_original_p != NULL, "RLC AM PDU Segment Error: Empty block sn=%d vtA=%d vtS=%d LcId=%d !\n", + sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + + + AssertFatal (pdu_mngt->payload == mb_original_p->data + sizeof(struct mac_tb_req) + pdu_mngt->header_and_payload_size - pdu_mngt->payload_size, + "RLC AM PDU Segment Error: Inconsistent data pointers p1=%p p2=%p sn = %d total size = %d data size = %d LcId=%d !\n", + pdu_mngt->payload,mb_original_p->data + sizeof(struct mac_tb_req),pdu_mngt->header_and_payload_size,pdu_mngt->payload_size,sn,rlc_pP->channel_id); + + /* Init ReTx Hole list if not configured, ie the whole PDU has to be retransmitted */ + if (pdu_mngt->num_holes == 0) + { + AssertFatal (pdu_mngt->retx_payload_size == pdu_mngt->payload_size,"RLC AM PDU ReTx Segment: Expecting full PDU size ReTxSize=%d DataSize=%d sn=%d vtA=%d vtS=%d LcId=%d !\n", + pdu_mngt->retx_payload_size,pdu_mngt->payload_size,sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + pdu_mngt->retx_hole_index = 0; + pdu_mngt->hole_so_start[0] = 0; + pdu_mngt->hole_so_stop[0] = pdu_mngt->payload_size - 1; + pdu_mngt->num_holes = 1; + } + + /* Init SO Start and SO Stop */ + retx_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index]; + retx_so_stop = pdu_mngt->hole_so_stop[pdu_mngt->retx_hole_index]; + + AssertFatal ((retx_so_start <= retx_so_stop) && (retx_so_stop - retx_so_start + 1 <= pdu_mngt->payload_size), + "RLC AM Tx PDU Segment Data SO Error: retx_so_start=%d retx_so_stop=%d OriginalPDUDataLength=%d sn=%d LcId=%d!\n", + retx_so_start,retx_so_stop,pdu_mngt->payload_size,sn,rlc_pP->channel_id); + + /* Init FI to the same value as original PDU */ + fi_start = (!(RLC_AM_PDU_GET_FI_START(*(pdu_mngt->first_byte)))); + fi_end = (!(RLC_AM_PDU_GET_FI_END(*(pdu_mngt->first_byte)))); + + /* Handle no LI case first */ + if (num_LIs_pdu_segment == 0) + { + /* Bound retx_so_stop to available TBS */ + if (retx_so_stop - retx_so_start + 1 + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE > rlc_pP->nb_bytes_requested_by_mac) + { + retx_so_stop = retx_so_start + rlc_pP->nb_bytes_requested_by_mac - RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE - 1; + } + + *payload_sizeP = retx_so_stop - retx_so_start + 1; + + mem_pdu_segment_p = get_free_mem_block((*payload_sizeP + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + sizeof(struct mac_tb_req)), __func__); + pdu_segment_header_p = (uint8_t *)&mem_pdu_segment_p->data[sizeof(struct mac_tb_req)]; + ((struct mac_tb_req*)(mem_pdu_segment_p->data))->data_ptr = pdu_segment_header_p; + ((struct mac_tb_req*)(mem_pdu_segment_p->data))->tb_size = RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + *payload_sizeP; + + /* clear all PDU segment */ + memset(pdu_segment_header_p, 0, *payload_sizeP + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE); + /* copy data part */ + memcpy(pdu_segment_header_p + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE, pdu_mngt->payload + retx_so_start, *payload_sizeP); + + /* Set FI part to false if SO Start and SO End are different from PDU boundaries */ + if (retx_so_start) + { + fi_start = FALSE; + } + if (retx_so_stop < pdu_mngt->payload_size - 1) + { + fi_end = FALSE; + } + + /* Header content is filled at the end */ + } + else + { + /* Step 1 */ + /* Find the SDU index in the original PDU containing retx_so_start */ + sdu_size_t sdu_size = 0; + sdu_size_t data_size = 0; + *payload_sizeP = 0; + sdu_size_t header_segment_length = RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE; + pdu_original_header_p = pdu_mngt->first_byte + 2; + li_bit_offset = 4; /* toggle between 0 and 4 */ + li_jump_offset = 1; /* toggle between 1 and 2 */ + uint16_t temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1)); + + + /* Read first LI */ + sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset); + pdu_original_header_p += li_jump_offset; + li_bit_offset ^= 0x4; + li_jump_offset ^= 0x3; + data_size += sdu_size; + sdu_index = 1; + + /* Loop on all original LIs */ + while ((data_size < retx_so_start + 1) && (sdu_index < pdu_mngt->nb_sdus)) + { + if (sdu_index < pdu_mngt->nb_sdus - 1) + { + temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1)); + sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset); + pdu_original_header_p += li_jump_offset; + li_bit_offset ^= 0x4; + li_jump_offset ^= 0x3; + data_size += sdu_size; + } + else + { + /* if retx_so_start is still not included then set data_size with full original PDU data size */ + /* Set fi_start to FALSE in this case */ + data_size = pdu_mngt->payload_size; + } + sdu_index ++; + } + + if (retx_so_start == data_size) + { + /* Set FI Start if retx_so_start = cumulated data size */ + fi_start = TRUE; + /* there must be at least one SDU more */ + AssertFatal (sdu_index < pdu_mngt->nb_sdus, "RLC AM Tx PDU Segment Error: sdu_index=%d nb_sdus=%d sn=%d LcId=%d !\n", + sdu_index,pdu_mngt->nb_sdus,sn,rlc_pP->channel_id); + if (sdu_index < pdu_mngt->nb_sdus - 1) + { + temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1)); + sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset); + pdu_original_header_p += li_jump_offset; + li_bit_offset ^= 0x4; + li_jump_offset ^= 0x3; + data_size += sdu_size; + } + else + { + /* It was the last LI, then set data_size to full original PDU size */ + data_size = pdu_mngt->payload_size; + } + /* Go to next SDU */ + sdu_index ++; + } + else if (retx_so_start != 0) + { + /* in all other cases set fi_start to FALSE if it SO Start is not 0 */ + fi_start = FALSE; + } + + /* Set first SDU portion of the segment */ + sdus_segment_size[0] = data_size - retx_so_start; + + /* Check if so end is in the first SDU portion */ + if (sdus_segment_size[0] >= retx_so_stop - retx_so_start + 1) + { + sdus_segment_size[0] = retx_so_stop - retx_so_start + 1; + *payload_sizeP = sdus_segment_size[0]; + num_LIs_pdu_segment = 0; + } + + /* Bound first SDU segment to available TBS if necessary */ + if (sdus_segment_size[0] + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE >= rlc_pP->nb_bytes_requested_by_mac) + { + sdus_segment_size[0] = rlc_pP->nb_bytes_requested_by_mac - RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE; + *payload_sizeP = sdus_segment_size[0]; + num_LIs_pdu_segment = 0; + } + + + /* Now look for the end if it was not set previously */ + if (*payload_sizeP == 0) + { + sdu_segment_index ++; + while ((sdu_index < pdu_mngt->nb_sdus) && (data_size < retx_so_stop + 1)) + { + if (sdu_index < pdu_mngt->nb_sdus - 1) + { + temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1)); + sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset); + pdu_original_header_p += li_jump_offset; + li_bit_offset ^= 0x4; + li_jump_offset ^= 0x3; + data_size += sdu_size; + } + else + { + sdu_size = pdu_mngt->payload_size - data_size; + data_size = pdu_mngt->payload_size; + } + + sdus_segment_size[sdu_segment_index] = sdu_size; + sdu_index ++; + sdu_segment_index ++; + } + + + if (data_size > retx_so_stop + 1) + { + sdus_segment_size[sdu_segment_index - 1] = retx_so_stop - (data_size - sdu_size) + 1; + } + + /* Set number of LIs in the segment */ + num_LIs_pdu_segment = sdu_segment_index - 1; + + AssertFatal (num_LIs_pdu_segment <= pdu_mngt->nb_sdus - 1, "RLC AM Tx PDU Segment Data Error: nbLISegment=%d nbLIPDU=%d sn=%d LcId=%d !\n", + num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id); + + /* Bound to available TBS taking into account min PDU segment header*/ + sdu_segment_index = 0; + while ((sdu_segment_index < num_LIs_pdu_segment + 1) && (rlc_pP->nb_bytes_requested_by_mac > *payload_sizeP + RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index))) + { + AssertFatal (sdus_segment_size[sdu_segment_index] > 0, "RLC AM Tx PDU Segment Data Error: EMpty LI index=%d numLISegment=%d numLIPDU=%d PDULength=%d SOStart=%d SOStop=%d sn=%d LcId=%d !\n", + sdu_segment_index,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,pdu_mngt->payload_size,retx_so_start,retx_so_stop,sn,rlc_pP->channel_id); + + /* Add next sdu_segment_index to data part */ + if (RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index) + (*payload_sizeP) + sdus_segment_size[sdu_segment_index] <= rlc_pP->nb_bytes_requested_by_mac) + { + (*payload_sizeP) += sdus_segment_size[sdu_segment_index]; + } + else + { + /* bound to available TBS size */ + sdus_segment_size[sdu_segment_index] = rlc_pP->nb_bytes_requested_by_mac - RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index) - (*payload_sizeP); + (*payload_sizeP) += sdus_segment_size[sdu_segment_index]; + } + header_segment_length = RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index); + sdu_segment_index ++; + } + + num_LIs_pdu_segment = sdu_segment_index - 1; + } + + + /* update retx_so_stop */ + retx_so_stop = retx_so_start + (*payload_sizeP) - 1; + + AssertFatal ((retx_so_stop <= pdu_mngt->payload_size - 1) && (retx_so_stop - retx_so_start + 1 < pdu_mngt->payload_size), + "RLC AM Tx PDU Segment Data Error: retx_so_stop=%d OriginalPDUDataLength=%d SOStart=%d SegmentLength=%d numLISegment=%d numLIPDU=%d sn=%d LcId=%d !\n", + retx_so_stop,pdu_mngt->payload_size,retx_so_start,*payload_sizeP,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id); + + /* init FI End to FALSE if retx_so_stop is not end of PDU */ + if (retx_so_stop != pdu_mngt->payload_size - 1) + { + fi_end = FALSE; + } + + /* Check consistency between sdus_segment_size and payload_sizeP */ + /* And Set FI End if retx_so_stop = cumulated data size and this is not last SDU */ + data_size = 0; + for (int i = 0; i < num_LIs_pdu_segment + 1; i++) + { + data_size += sdus_segment_size[i]; + if ((retx_so_stop == data_size - 1) && (i < num_LIs_pdu_segment)) + { + fi_end = TRUE; + } + } + + AssertFatal (data_size == *payload_sizeP, "RLC AM Tx PDU Segment Data Error: SduSum=%d Data=%d sn=%d LcId=%d !\n", + data_size,*payload_sizeP,sn,rlc_pP->channel_id); + + + + /* Allocation */ + AssertFatal (header_segment_length + *payload_sizeP <= pdu_mngt->header_and_payload_size + 2, "RLC AM PDU Segment Error: Hdr=%d Data=%d Original Hdr+Data =%d sn=%d LcId=%d !\n", + header_segment_length,*payload_sizeP,pdu_mngt->header_and_payload_size,sn,rlc_pP->channel_id); + mem_pdu_segment_p = get_free_mem_block((*payload_sizeP + header_segment_length + sizeof(struct mac_tb_req)), __func__); + pdu_segment_header_p = (uint8_t *)&mem_pdu_segment_p->data[sizeof(struct mac_tb_req)]; + ((struct mac_tb_req*)(mem_pdu_segment_p->data))->data_ptr = pdu_segment_header_p; + ((struct mac_tb_req*)(mem_pdu_segment_p->data))->tb_size = header_segment_length + *payload_sizeP; + + /* clear all PDU segment */ + memset(pdu_segment_header_p, 0, *payload_sizeP + header_segment_length); + /* copy data part */ + memcpy(pdu_segment_header_p + header_segment_length, pdu_mngt->payload + retx_so_start, *payload_sizeP); + } + + /* Last step : update contexts and fill PDU Segment Header */ + if (mem_pdu_segment_p != NULL) + { + /* Update PDU Segment contexts */ + if (*payload_sizeP == pdu_mngt->hole_so_stop[pdu_mngt->retx_hole_index] - pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index] + 1) + { + /* All data in the segment are transmitted : switch to next one */ + pdu_mngt->retx_hole_index ++; + if (pdu_mngt->retx_hole_index < pdu_mngt->num_holes) + { + /* Set min SOStart to the value of next hole : assumption is holes are ordered by increasing SOStart */ + pdu_mngt->nack_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index]; + } + else + { + /* no more scheduled Retx: reset values */ + /* Retx size is reset in the calling function */ + pdu_mngt->num_holes = 0; + pdu_mngt->retx_hole_index = 0; + pdu_mngt->nack_so_start = 0; + } + } + else + { + /* not all segment data could be transmitted, just update SoStart */ + pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index] += (*payload_sizeP); + pdu_mngt->nack_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index]; + } + + /* Content is supposed to be init with 0 so with FIStart=FIEnd=TRUE */ + RLC_AM_PDU_SET_D_C(*pdu_segment_header_p); + RLC_AM_PDU_SET_RF(*pdu_segment_header_p); + /* Change FI */ + if (!fi_start) + { + // Set to not starting + (*pdu_segment_header_p) |= (1 << (RLC_AM_PDU_FI_OFFSET + 1)); + } + if (!fi_end) + { + // Set to not starting + (*pdu_segment_header_p) |= (1 << (RLC_AM_PDU_FI_OFFSET)); + } + /* Set SN */ + (*pdu_segment_header_p) |= ((sn >> 8) & 0x3); + (*(pdu_segment_header_p + 1)) |= (sn & 0xFF); + + /* Segment Offset */ + header_so_part = retx_so_start; + + /* Last Segment Flag (LSF) */ + if (retx_so_stop == pdu_mngt->payload_size - 1) + { + RLC_AM_PDU_SET_LSF(header_so_part); + } + + /* Store SO bytes */ + * (pdu_segment_header_p + 2) = (header_so_part >> 8) & 0xFF; + * (pdu_segment_header_p + 3) = header_so_part & 0xFF; + + /* Fill LI part */ + if (num_LIs_pdu_segment) + { + uint16_t index = 0; + uint16_t temp = 0; + /* Set Extension bit in first byte */ + RLC_AM_PDU_SET_E(*pdu_segment_header_p); + + /* loop on nb of LIs */ + pdu_segment_header_p += RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE; + li_bit_offset = 4; /* toggle between 0 and 4 */ + li_jump_offset = 1; /* toggle between 1 and 2 */ + + while (index < num_LIs_pdu_segment) + { + /* Set E bit for next LI if present */ + if (index < num_LIs_pdu_segment - 1) + RLC_SET_BIT(temp,li_bit_offset + RLC_AM_LI_BITS); + /* Set LI */ + RLC_AM_PDU_SET_LI(temp,sdus_segment_size[index],li_bit_offset); + *pdu_segment_header_p = temp >> 8; + *(pdu_segment_header_p + 1) = temp & 0xFF; + pdu_segment_header_p += li_jump_offset; + li_bit_offset ^= 0x4; + li_jump_offset ^= 0x3; + + temp = ((*pdu_segment_header_p) << 8) | (*(pdu_segment_header_p + 1)); + index ++; + } + } + } + else + { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] OUT OF MEMORY PDU SN %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + sn); + } + + return mem_pdu_segment_p; } + +#if 0 //----------------------------------------------------------------------------- mem_block_t* rlc_am_retransmit_get_subsegment( const protocol_ctxt_t* const ctxt_pP, @@ -340,7 +709,7 @@ mem_block_t* rlc_am_retransmit_get_subsegment( // - set the header of the new AMD PDU segment in accordance with the description in sub clause 6.; // - set the P field according to sub clause 5.2.2. - mem_block_t* mb_original_p = rlc_pP->pdu_retrans_buffer[snP].mem_block; + mem_block_t* mb_original_p = rlc_pP->tx_data_pdu_buffer[snP].mem_block; if (mb_original_p != NULL) { mem_block_t* mb_sub_segment_p = get_free_mem_block(*sizeP + sizeof(struct mac_tb_req), __func__); @@ -353,10 +722,10 @@ mem_block_t* rlc_am_retransmit_get_subsegment( ((struct mac_tb_req*)(mb_sub_segment_p->data))->data_ptr = (uint8_t*)&(mb_sub_segment_p->data[sizeof(struct mac_tb_req)]); - if (rlc_am_get_data_pdu_infos(ctxt_pP, rlc_pP, pdu_original_p, rlc_pP->pdu_retrans_buffer[snP].header_and_payload_size, &pdu_info) >= 0) { + if (rlc_am_get_data_pdu_infos(ctxt_pP, rlc_pP, pdu_original_p, rlc_pP->tx_data_pdu_buffer[snP].header_and_payload_size, &pdu_info) >= 0) { int li_index = 0; - int start_offset = rlc_pP->pdu_retrans_buffer[snP].nack_so_start; - int stop_offset = rlc_pP->pdu_retrans_buffer[snP].nack_so_stop; + int start_offset = rlc_pP->tx_data_pdu_buffer[snP].nack_so_start; + int stop_offset = rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop; LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] ORIGINAL PDU SN %04d:\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), @@ -366,8 +735,8 @@ mem_block_t* rlc_am_retransmit_get_subsegment( // all 15 bits set to 1 (indicate that the missing portion of the AMD PDU includes all bytes // to the last byte of the AMD PDU) if (stop_offset == 0x7FFF) { - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = rlc_pP->pdu_retrans_buffer[snP].payload_size - 1; - stop_offset = rlc_pP->pdu_retrans_buffer[snP].nack_so_stop; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = rlc_pP->tx_data_pdu_buffer[snP].payload_size - 1; + stop_offset = rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop; LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] UPDATED RETRANS PDU SN %04d nack_so_stop FROM 0x7FFF to %05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, @@ -627,7 +996,7 @@ mem_block_t* rlc_am_retransmit_get_subsegment( PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); test_pdu_copy_size = max_copy_payload_size; - if ((stop_offset == (start_offset + max_copy_payload_size - 1)) && (stop_offset == rlc_pP->pdu_retrans_buffer[snP].payload_size - 1)) { + if ((stop_offset == (start_offset + max_copy_payload_size - 1)) && (stop_offset == rlc_pP->tx_data_pdu_buffer[snP].payload_size - 1)) { not_test_fi = (not_test_fi & 0x2) | (not_fi_original & 0x1); // set b0 idendical to the b0 of the non segmented PDU } else { not_test_fi = not_test_fi & 0x2; // clear b0 because no SDU ending in this PDU @@ -635,7 +1004,7 @@ mem_block_t* rlc_am_retransmit_get_subsegment( } //--------------------------------------------------------------- - /*if (stop_offset == (rlc_pP->pdu_retrans_buffer[snP].payload_size - 1)) { + /*if (stop_offset == (rlc_pP->tx_data_pdu_buffer[snP].payload_size - 1)) { test_fi = (test_fi & 0x02) | (fi_original & 0x01); }*/ //--------------------------------------------------------------- @@ -692,16 +1061,16 @@ mem_block_t* rlc_am_retransmit_get_subsegment( // copy payload to retransmit //--------------------------------------------------------------- memcpy(fill_payload_p, - &rlc_pP->pdu_retrans_buffer[snP].payload[start_offset], + &rlc_pP->tx_data_pdu_buffer[snP].payload[start_offset], test_pdu_copy_size); ((struct mac_tb_req*)(mb_sub_segment_p->data))->tb_size = (tb_size_t)(((uint64_t)fill_payload_p)+ test_pdu_copy_size) - ((uint64_t)(&pdu_sub_segment_p->b1)); // set LSF - if ((test_pdu_copy_size + start_offset) == rlc_pP->pdu_retrans_buffer[snP].payload_size) { + if ((test_pdu_copy_size + start_offset) == rlc_pP->tx_data_pdu_buffer[snP].payload_size) { pdu_sub_segment_p->data[0] = pdu_sub_segment_p->data[0] | 0x80; - rlc_pP->pdu_retrans_buffer[snP].flags.retransmit = 0; + rlc_pP->tx_data_pdu_buffer[snP].flags.retransmit = 0; LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] RE-SEND DATA PDU SN %04d SO %d %d BYTES PAYLOAD %d BYTES LSF!\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), @@ -728,15 +1097,15 @@ mem_block_t* rlc_am_retransmit_get_subsegment( // update nack_so_start //--------------------------------------------------------------- rlc_am_remove_hole(ctxt_pP, rlc_pP, snP, start_offset, test_pdu_copy_size+start_offset - 1); - //rlc_pP->pdu_retrans_buffer[snP].nack_so_start = rlc_pP->pdu_retrans_buffer[snP].nack_so_start + test_pdu_copy_size; + //rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = rlc_pP->tx_data_pdu_buffer[snP].nack_so_start + test_pdu_copy_size; LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] RE-SEND DATA PDU SN %04d NOW nack_so_start %d nack_so_stop %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, - rlc_pP->pdu_retrans_buffer[snP].nack_so_start, - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop); - /*if (rlc_pP->pdu_retrans_buffer[snP].nack_so_start == rlc_pP->pdu_retrans_buffer[snP].nack_so_stop) { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = 0; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = 0x7FFF; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start, + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop); + /*if (rlc_pP->tx_data_pdu_buffer[snP].nack_so_start == rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop) { + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = 0; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = 0x7FFF; }*/ } else { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] COULD NOT GET INFO FOR DATA PDU SN %04d -> RETURN NULL\n", @@ -744,8 +1113,6 @@ mem_block_t* rlc_am_retransmit_get_subsegment( snP); return NULL; } - - rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sub_segment_p, test_pdu_copy_size); return mb_sub_segment_p; } else { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] RE-SEND DATA PDU SN %04d BUT NO PDU AVAILABLE -> RETURN NULL\n", @@ -755,6 +1122,7 @@ mem_block_t* rlc_am_retransmit_get_subsegment( return NULL; } } +#endif //----------------------------------------------------------------------------- void rlc_am_tx_buffer_display ( const protocol_ctxt_t* const ctxt_pP, @@ -763,6 +1131,7 @@ void rlc_am_tx_buffer_display ( { rlc_sn_t sn = rlc_pP->vt_a; int i, loop = 0; + rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p; if (message_pP) { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" Retransmission buffer %s VT(A)=%04d VT(S)=%04d:", @@ -778,25 +1147,26 @@ void rlc_am_tx_buffer_display ( } while (rlc_pP->vt_s != sn) { - if (rlc_pP->pdu_retrans_buffer[sn].mem_block) { + tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE]; + if (tx_data_pdu_buffer_p->mem_block) { if ((loop % 1) == 0) { LOG_D(RLC, "\nTX SN:\t"); } - if (rlc_pP->pdu_retrans_buffer[sn].flags.retransmit) { - LOG_D(RLC, "%04d %d/%d Bytes (NACK RTX:%02d ",sn, rlc_pP->pdu_retrans_buffer[sn].header_and_payload_size, rlc_pP->pdu_retrans_buffer[sn].payload_size, - rlc_pP->pdu_retrans_buffer[sn].retx_count); + if (tx_data_pdu_buffer_p->flags.retransmit) { + LOG_D(RLC, "%04d %d/%d Bytes (NACK RTX:%02d ",sn, tx_data_pdu_buffer_p->header_and_payload_size, tx_data_pdu_buffer_p->payload_size, + tx_data_pdu_buffer_p->retx_count); } else { - LOG_D(RLC, "%04d %d/%d Bytes (RTX:%02d ",sn, rlc_pP->pdu_retrans_buffer[sn].header_and_payload_size, rlc_pP->pdu_retrans_buffer[sn].payload_size, - rlc_pP->pdu_retrans_buffer[sn].retx_count); + LOG_D(RLC, "%04d %d/%d Bytes (RTX:%02d ",sn, tx_data_pdu_buffer_p->header_and_payload_size, tx_data_pdu_buffer_p->payload_size, + tx_data_pdu_buffer_p->retx_count); } - if (rlc_pP->pdu_retrans_buffer[sn].num_holes == 0) { - LOG_D(RLC, "SO:%04d->%04d)\t", rlc_pP->pdu_retrans_buffer[sn].nack_so_start, rlc_pP->pdu_retrans_buffer[sn].nack_so_stop); + if (tx_data_pdu_buffer_p->num_holes == 0) { + LOG_D(RLC, "SO:%04d->%04d)\t", tx_data_pdu_buffer_p->nack_so_start, tx_data_pdu_buffer_p->nack_so_stop); } else { - for (i=0; i<rlc_pP->pdu_retrans_buffer[sn].num_holes; i++) { + for (i=0; i<tx_data_pdu_buffer_p->num_holes; i++) { assert(i < RLC_AM_MAX_HOLES_REPORT_PER_PDU); - LOG_D(RLC, "SO:%04d->%04d)\t", rlc_pP->pdu_retrans_buffer[sn].hole_so_start[i], rlc_pP->pdu_retrans_buffer[sn].hole_so_stop[i]); + LOG_D(RLC, "SO:%04d->%04d)\t", tx_data_pdu_buffer_p->hole_so_start[i], tx_data_pdu_buffer_p->hole_so_stop[i]); } } @@ -808,6 +1178,132 @@ void rlc_am_tx_buffer_display ( LOG_D(RLC, "\n"); } + +//----------------------------------------------------------------------------- +mem_block_t * rlc_am_get_pdu_to_retransmit( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t* const rlc_pP) +{ + rlc_sn_t sn = rlc_pP->vt_a; + rlc_sn_t sn_end = rlc_pP->vt_s; + mem_block_t* pdu_p = NULL; + rlc_am_tx_data_pdu_management_t* tx_data_pdu_management; + + AssertFatal ((rlc_pP->retrans_num_pdus > 0) && (rlc_pP->vt_a != rlc_pP->vt_s), "RLC AM ReTx start process Error: NbPDUtoRetx=%d vtA=%d vtS=%d LcId=%d !\n", + rlc_pP->retrans_num_pdus,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + + do + { + tx_data_pdu_management = &rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE]; + if ((tx_data_pdu_management->flags.retransmit) && (tx_data_pdu_management->flags.max_retransmit == 0)) + { + AssertFatal (tx_data_pdu_management->sn == sn, "RLC AM ReTx PDU Error: SN Error pdu_sn=%d sn=%d vtA=%d vtS=%d LcId=%d !\n", + tx_data_pdu_management->sn,sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + AssertFatal (tx_data_pdu_management->flags.transmitted == 1, "RLC AM ReTx PDU Error: State Error sn=%d vtA=%d vtS=%d LcId=%d !\n", + sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + AssertFatal (tx_data_pdu_management->retx_payload_size > 0, "RLC AM ReTx PDU Error: No Data to Retx sn=%d vtA=%d vtS=%d LcId=%d !\n", + sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + + /* Either the whole RLC PDU is to be transmitted and there is enough MAC TBS or there is minimum TBS size for transmitting 1 AM PDU segment */ + if ((tx_data_pdu_management->retx_payload_size == tx_data_pdu_management->payload_size) && (rlc_pP->nb_bytes_requested_by_mac >= tx_data_pdu_management->header_and_payload_size)) + { + /* check maxretx is not hit */ + if (tx_data_pdu_management->retx_count_next <= rlc_pP->max_retx_threshold) + { + pdu_p = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, sn); + + if (pdu_p != NULL) + { + rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_management->retx_payload_size; + rlc_pP->retrans_num_pdus --; + tx_data_pdu_management->retx_payload_size = 0; + tx_data_pdu_management->flags.retransmit = 0; + + // update stats + rlc_pP->stat_tx_data_pdu += 1; + rlc_pP->stat_tx_retransmit_pdu += 1; + rlc_pP->stat_tx_retransmit_pdu_by_status += 1; + rlc_pP->stat_tx_data_bytes += tx_data_pdu_management->payload_size; + rlc_pP->stat_tx_retransmit_bytes += tx_data_pdu_management->payload_size; + rlc_pP->stat_tx_retransmit_bytes_by_status += tx_data_pdu_management->payload_size; + + } + } + else + { + // TO DO : RLC Notification to RRC + ReEstablishment procedure + tx_data_pdu_management->flags.max_retransmit = 1; + LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RLC AM MAX RETX=%d] SN %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + tx_data_pdu_management->retx_count_next, + sn); + } + } + else if (rlc_pP->nb_bytes_requested_by_mac >= 5) + { + /* Resegmentation case */ + /* check maxretx is not hit */ + if (tx_data_pdu_management->retx_count_next <= rlc_pP->max_retx_threshold) + { + sdu_size_t pdu_data_size = 0; + + pdu_p = rlc_am_retransmit_get_am_segment(ctxt_pP, rlc_pP, tx_data_pdu_management,&pdu_data_size); + + if (pdu_p != NULL) + { + AssertFatal ((tx_data_pdu_management->retx_payload_size >= pdu_data_size) && (rlc_pP->retrans_num_bytes_to_retransmit >= pdu_data_size), "RLC AM ReTx PDU Segment Error: DataSize=%d PDUReTxsize=%d TotalReTxsize=%d sn=%d LcId=%d !\n", + pdu_data_size,tx_data_pdu_management->retx_payload_size,rlc_pP->retrans_num_bytes_to_retransmit,sn,rlc_pP->channel_id); + + tx_data_pdu_management->retx_payload_size -= pdu_data_size; + rlc_pP->retrans_num_bytes_to_retransmit -= pdu_data_size; + if (tx_data_pdu_management->retx_payload_size == 0) + { + rlc_pP->retrans_num_pdus --; + tx_data_pdu_management->retx_payload_size = 0; + tx_data_pdu_management->flags.retransmit = 0; + } + + // update stats + rlc_pP->stat_tx_data_pdu += 1; + rlc_pP->stat_tx_retransmit_pdu += 1; + rlc_pP->stat_tx_retransmit_pdu_by_status += 1; + rlc_pP->stat_tx_data_bytes += pdu_data_size; + rlc_pP->stat_tx_retransmit_bytes += pdu_data_size; + rlc_pP->stat_tx_retransmit_bytes_by_status += pdu_data_size; + + } + } + else + { + // TO DO : RLC Notification to RRC + ReEstablishment procedure + tx_data_pdu_management->flags.max_retransmit = 1; + LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RLC AM MAX RETX=%d] SN %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + tx_data_pdu_management->retx_count_next, + sn); + } + } + + if (pdu_p != NULL) + { + /* check polling */ + rlc_am_pdu_sn_10_t* pdu_header_p = (rlc_am_pdu_sn_10_t*) (&pdu_p->data[sizeof(struct mac_tb_req)]); + rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_header_p, tx_data_pdu_management->payload_size,false); + + tx_data_pdu_management->retx_count = tx_data_pdu_management->retx_count_next; + + break; + } + + } + + sn = RLC_AM_NEXT_SN(sn); + } while((sn != sn_end) && (rlc_pP->retrans_num_pdus > 0)); + + return pdu_p; +} + +#if 0 //----------------------------------------------------------------------------- void rlc_am_retransmit_any_pdu( const protocol_ctxt_t* const ctxt_pP, @@ -824,13 +1320,13 @@ void rlc_am_retransmit_any_pdu( PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); while (sn != sn_end) { - if (rlc_pP->pdu_retrans_buffer[sn].mem_block != NULL) { + if (rlc_pP->tx_data_pdu_buffer[sn].mem_block != NULL) { if (!found_pdu) { found_pdu = 1; found_pdu_sn = sn; } - if (rlc_pP->pdu_retrans_buffer[sn].header_and_payload_size <= rlc_pP->nb_bytes_requested_by_mac) { + if (rlc_pP->tx_data_pdu_buffer[sn].header_and_payload_size <= rlc_pP->nb_bytes_requested_by_mac) { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[FORCE-TRAFFIC] RE-SEND DATA PDU SN %04d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), sn); @@ -843,12 +1339,13 @@ void rlc_am_retransmit_any_pdu( // no need for update rlc_pP->nb_bytes_requested_by_mac pdu_p = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, sn); pdu_sn_10_p = (rlc_am_pdu_sn_10_t*) (&pdu_p->data[sizeof(struct mac_tb_req)]); - rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->pdu_retrans_buffer[sn].header_and_payload_size); - pdu_sn_10_p->b1 = pdu_sn_10_p->b1 | 0x20; - rlc_pP->c_pdu_without_poll = 0; - rlc_pP->c_byte_without_poll = 0; + rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->tx_data_pdu_buffer[sn].header_and_payload_size,false); + //BugFix: polling is checked and done in function above ! + //pdu_sn_10_p->b1 = pdu_sn_10_p->b1 | 0x20; + //BugFix : pdu_without_poll and byte_without_poll are reset only if a Poll is transmitted + //rlc_pP->c_pdu_without_poll = 0; + //rlc_pP->c_byte_without_poll = 0; //rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK; - rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP); rlc_pP->stat_tx_data_pdu += 1; rlc_pP->stat_tx_retransmit_pdu += 1; rlc_pP->stat_tx_data_bytes += ((struct mac_tb_req*)(pdu_p->data))->tb_size; @@ -877,12 +1374,11 @@ void rlc_am_retransmit_any_pdu( rlc_am_nack_pdu (ctxt_pP, rlc_pP, found_pdu_sn, 0, 0x7FFF); pdu_p = rlc_am_retransmit_get_subsegment(ctxt_pP, rlc_pP, found_pdu_sn, &rlc_pP->nb_bytes_requested_by_mac); pdu_sn_10_p = (rlc_am_pdu_sn_10_t*) (&pdu_p->data[sizeof(struct mac_tb_req)]); - rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->pdu_retrans_buffer[found_pdu_sn].header_and_payload_size); + rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->tx_data_pdu_buffer[found_pdu_sn].header_and_payload_size,false); pdu_sn_10_p->b1 = pdu_sn_10_p->b1 | 0x20; rlc_pP->c_pdu_without_poll = 0; rlc_pP->c_byte_without_poll = 0; //rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK; - rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP); rlc_pP->stat_tx_data_pdu += 1; rlc_pP->stat_tx_retransmit_pdu += 1; rlc_pP->stat_tx_data_bytes += ((struct mac_tb_req*)(pdu_p->data))->tb_size; @@ -896,3 +1392,4 @@ void rlc_am_retransmit_any_pdu( } } } +#endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h index 99570e5d7f4d8be8ef57823503887c797bcca9b6..338bc791968565aba6640d19f2e6dc181c30695c 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h @@ -50,21 +50,24 @@ # define public_rlc_am_retransmit(x) extern x # endif # endif -/*! \fn void rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, uint16_t snP, sdu_size_t so_startP, sdu_size_t so_endP) +/*! \fn boolean_t rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, int16_t snP, int16_t prev_nack_snP,sdu_size_t so_startP, sdu_size_t so_endP) * \brief The RLC AM PDU which have the sequence number snP is marked NACKed with segment offset fields. * \param[in] ctxtP Running context. * \param[in] rlcP RLC AM protocol instance pointer. * \param[in] snP Sequence number of the PDU that is negative acknowledged. +* \param[in] prev_nack_snP Sequence number of previous PDU that is negative acknowledged. * \param[in] so_startP Start of the segment offset of the PDU that . * \param[in] so_endP Transport blocks received from MAC layer. +* \return OK/KO * \note It may appear a new hole in the retransmission buffer depending on the segment offset informations. Depending on the state of the retransmission buffer, negative confirmation can be sent to higher layers about the drop by the RLC AM instance of a particular SDU. */ -protected_rlc_am_retransmit(void rlc_am_nack_pdu ( +protected_rlc_am_retransmit(boolean_t rlc_am_nack_pdu ( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, const rlc_sn_t snP, - const sdu_size_t so_startP, - const sdu_size_t so_endP);) + const rlc_sn_t prev_nack_snP, + sdu_size_t so_startP, + sdu_size_t so_endP);) /*! \fn void rlc_am_ack_pdu (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP, rlc_sn_t snP) * \brief The RLC AM PDU which have the sequence number snP is marked ACKed. @@ -90,6 +93,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_copy ( rlc_am_entity_t *const rlcP, const rlc_sn_t snP)); +#if 0 /*! \fn mem_block_t* rlc_am_retransmit_get_subsegment (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP,rlc_sn_t snP, sdu_size_t *sizeP) * \brief The RLC AM PDU which have the sequence number snP is marked ACKed. * \param[in] ctxtP Running context. @@ -103,7 +107,18 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment ( rlc_am_entity_t *const rlcP, const rlc_sn_t snP, sdu_size_t *const sizeP)); +#endif +/*! \fn mem_block_t* rlc_am_get_pdu_to_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* rlcP) +* \brief Find a PDU or PDU segment to retransmit. +* \param[in] ctxtP Running context. +* \param[in] rlcP RLC AM protocol instance pointer. +* \return A copy of the retransmitted PDU or PDU segment or NULL if TBS was not big enough +*/ +protected_rlc_am_retransmit(mem_block_t* rlc_am_get_pdu_to_retransmit( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t* const rlcP);) +#if 0 /*! \fn void rlc_am_retransmit_any_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* rlcP) * \brief Retransmit any PDU in order to unblock peer entity, if no suitable PDU is found (depending on requested MAC size) to be retransmitted, then try to retransmit a subsegment of any PDU. * \param[in] ctxtP Running context. @@ -112,6 +127,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment ( protected_rlc_am_retransmit(void rlc_am_retransmit_any_pdu( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP);) +#endif /*! \fn void rlc_am_tx_buffer_display (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* rlcP, char* message_pP) * \brief Display the dump of the retransmission buffer. diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c index a9f0bdbf7e64e82155decfd4d8cd205415a99e45..cad1a776a8244503a7257fca0d3799c9d43d05d3 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c @@ -31,7 +31,812 @@ #include "UTIL/LOG/log.h" +boolean_t rlc_am_rx_check_vr_reassemble( + const protocol_ctxt_t* const ctxt_pP, + const rlc_am_entity_t* const rlc_pP) +{ + mem_block_t* cursor_p = rlc_pP->receiver_buffer.head; + rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = NULL; + sdu_size_t next_waited_so = 0; + boolean_t reassemble = FALSE; + + if (cursor_p != NULL) { + + rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + rlc_usn_t sn_ref = pdu_info_p->sn; + + if (sn_ref != rlc_pP->vr_r) { + /* Case vrR has advanced from head : most likely case */ + + reassemble = TRUE; + /* Handle first SN if it is made of PDU segments : set them all to be reassembled */ + if (pdu_info_p->rf) { + pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + next_waited_so = 0; + AssertFatal(pdu_cursor_mgnt_p->all_segments_received > 0,"AM Rx Check Reassembly head SN=%d with PDU segments != vrR=%d should be fully received LCID=%d\n", + sn_ref,rlc_pP->vr_r,rlc_pP->channel_id); + while ((cursor_p != NULL) && (pdu_info_p->sn == sn_ref) && (pdu_info_p->so == next_waited_so)) { + if (pdu_cursor_mgnt_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO) { + pdu_cursor_mgnt_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING; + } + next_waited_so += pdu_info_p->payload_size; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + } + + /* Now jump up to vrR */ + while ((RLC_AM_DIFF_SN(pdu_info_p->sn,sn_ref) < RLC_AM_DIFF_SN(rlc_pP->vr_r,sn_ref)) && (cursor_p != NULL)) { + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + + /* Handle vrR if it is made of incomplete PDU Segments */ + if ((cursor_p != NULL) && (pdu_info_p->sn == rlc_pP->vr_r)) { + pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + next_waited_so = 0; + AssertFatal(pdu_cursor_mgnt_p->all_segments_received == 0,"AM Rx Check Reassembly vr=%d should be partly received SNHead=%d LCID=%d\n", + rlc_pP->vr_r,sn_ref,rlc_pP->channel_id); + while ((cursor_p != NULL) && (pdu_info_p->sn == rlc_pP->vr_r) && (pdu_info_p->so == next_waited_so)) { + if (pdu_cursor_mgnt_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO) { + pdu_cursor_mgnt_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING; + } + next_waited_so += pdu_info_p->payload_size; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + } + } /* end sn_ref != rlc_pP->vr_r */ + else { + /* case vrR = partially received */ + + pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + next_waited_so = 0; + AssertFatal(pdu_cursor_mgnt_p->all_segments_received == 0,"AM Rx Check Reassembly SNHead=vr=%d should be partly received LCID=%d\n", + rlc_pP->vr_r,rlc_pP->channel_id); + while ((cursor_p != NULL) && (pdu_info_p->sn == rlc_pP->vr_r) && (pdu_info_p->so == next_waited_so)) { + if (pdu_cursor_mgnt_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO) { + pdu_cursor_mgnt_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING; + reassemble = TRUE; + } + next_waited_so += pdu_info_p->payload_size; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + } /*end sn_ref == rlc_pP->vr_r */ + } + return reassemble; +} + +mem_block_t * create_new_segment_from_pdu( + mem_block_t* const tb_pP, + uint16_t so_offset, /* offset from the data part of the PDU to copy */ + sdu_size_t data_length_to_copy) +{ + rlc_am_pdu_info_t* pdu_rx_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info; + rlc_am_pdu_info_t* pdu_new_segment_info_p = NULL; + mem_block_t * new_segment_p = NULL; + int16_t new_li_list[RLC_AM_MAX_SDU_IN_PDU]; + int16_t header_size = 0; + uint8_t num_li = 0; + boolean_t fi_start, fi_end, lsf; + + /* Init some PDU Segment header fixed parameters */ + fi_start = !((pdu_rx_info_p->fi & 0x2) >> 1); + fi_end = !(pdu_rx_info_p->fi & 0x1); + lsf = ((pdu_rx_info_p->lsf == 1) || (pdu_rx_info_p->rf == 0)); + + /* Handle NO Li case fist */ + if (pdu_rx_info_p->num_li == 0) { + + header_size = RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE; + + if (so_offset) { + fi_start = FALSE; + } + if (so_offset + data_length_to_copy != pdu_rx_info_p->payload_size) { + fi_end = FALSE; + lsf = FALSE; + } + } // end no LI in original segment + else { + + uint8_t li_index = 0; + uint16_t li_sum = 0; + num_li = pdu_rx_info_p->num_li; + + /* set LSF to false if we know that end of the original segment will not be copied */ + if (so_offset + data_length_to_copy != pdu_rx_info_p->payload_size) { + lsf = FALSE; + } + + /* catch the first LI containing so_offset */ + while ((li_index < pdu_rx_info_p->num_li) && (li_sum + pdu_rx_info_p->li_list[li_index] <= so_offset)) { + li_sum += pdu_rx_info_p->li_list[li_index]; + num_li --; + li_index ++; + } + + /* set FI start if so_offset = LI sum and at least one LI have been read */ + if ((li_index) && (so_offset == li_sum)) { + fi_start = TRUE; + } + + /* Fill LI until the end */ + if (num_li) { + sdu_size_t remaining_size = data_length_to_copy; + uint8_t j = 0; + new_li_list[0] = li_sum + pdu_rx_info_p->li_list[li_index] - so_offset; + if (data_length_to_copy <= new_li_list[0]) { + num_li = 0; + } + else { + remaining_size -= new_li_list[0]; + j++; + li_index ++; + while ((li_index < pdu_rx_info_p->num_li) && (remaining_size >= pdu_rx_info_p->li_list[li_index])) { + remaining_size -= pdu_rx_info_p->li_list[li_index]; + new_li_list[j] = pdu_rx_info_p->li_list[li_index]; + j++; + li_index ++; + } + + /* update number of LI in the segment */ + num_li = j; + /* set FI End if remaining size = 0 */ + if (remaining_size == 0) { + fi_end = TRUE; + } + } + } + + /* compute header size */ + header_size = RLC_AM_PDU_SEGMENT_HEADER_SIZE(num_li); + + } // end LIs in original segment + + /* Allocate new buffer */ + new_segment_p = get_free_mem_block(sizeof (mac_rlc_max_rx_header_size_t) + header_size + data_length_to_copy, __func__); + + /* Fill PDU Segment Infos and Header */ + if (new_segment_p != NULL) { + pdu_new_segment_info_p = &((rlc_am_rx_pdu_management_t*)(new_segment_p->data))->pdu_info; + rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (new_segment_p->data); + uint8_t *pdu_segment_header_p = (uint8_t *)&(new_segment_p->data[sizeof (mac_rlc_max_rx_header_size_t)]); + + pdu_cursor_mgnt_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO; //to be updated after if SN = vrR + + pdu_new_segment_info_p->d_c = pdu_rx_info_p->d_c; + pdu_new_segment_info_p->sn = pdu_rx_info_p->sn; + pdu_new_segment_info_p->p = pdu_rx_info_p->p; + pdu_new_segment_info_p->rf = 1; + pdu_new_segment_info_p->fi = (((fi_start ? 0: 1) << 1) | (fi_end ? 0: 1)); + pdu_new_segment_info_p->num_li = num_li; + pdu_new_segment_info_p->e = (num_li ? 1: 0); + pdu_new_segment_info_p->lsf = (lsf ? 1: 0); + pdu_new_segment_info_p->so = pdu_rx_info_p->so + so_offset; + pdu_new_segment_info_p->payload = pdu_segment_header_p + header_size; + pdu_new_segment_info_p->header_size = header_size; + pdu_new_segment_info_p->payload_size = data_length_to_copy; + pdu_new_segment_info_p->hidden_size = data_length_to_copy; + for (int i=0; i < num_li; i++) { + pdu_new_segment_info_p->li_list[i] = new_li_list[i]; + pdu_new_segment_info_p->hidden_size -= new_li_list[i]; + } + + /* Fill Header part in the buffer */ + /* Content is supposed to be init with 0 so with FIStart=FIEnd=TRUE */ + /* copy first two bytes from original: D/C + RF + FI + E+ SN*/ + memset(pdu_segment_header_p, 0, header_size); + RLC_AM_PDU_SET_D_C(*pdu_segment_header_p); + RLC_AM_PDU_SET_RF(*pdu_segment_header_p); + if (pdu_new_segment_info_p->p) { + RLC_AM_PDU_SET_POLL(*pdu_segment_header_p); + } + /* Change FI */ + if (!fi_start) + { + // Set to not starting + (*pdu_segment_header_p) |= (1 << (RLC_AM_PDU_FI_OFFSET + 1)); + + } + if (!fi_end) + { + // Set to not starting + (*pdu_segment_header_p) |= (1 << (RLC_AM_PDU_FI_OFFSET)); + + } + /* E */ + if (pdu_new_segment_info_p->e) { + RLC_AM_PDU_SET_E(*pdu_segment_header_p); + } + /* SN */ + (*pdu_segment_header_p) |= ((pdu_new_segment_info_p->sn >> 8) & 0x3); + *(pdu_segment_header_p + 1) = (pdu_new_segment_info_p->sn & 0xFF); + + pdu_segment_header_p += 2; + + /* Last Segment Flag (LSF) */ + if (lsf) + { + RLC_AM_PDU_SET_LSF(*pdu_segment_header_p); + } + /* Store SO bytes */ + * (pdu_segment_header_p ) |= ((pdu_new_segment_info_p->so >> 8) & 0x7F); + * (pdu_segment_header_p + 1) = pdu_new_segment_info_p->so & 0xFF; + + if (num_li) { + uint16_t index = 0; + uint16_t temp = 0; + uint8_t li_bit_offset = 4; /* toggle between 0 and 4 */ + uint8_t li_jump_offset = 1; /* toggle between 1 and 2 */ + + /* loop on nb of LIs */ + pdu_segment_header_p += 2; + + while (index < num_li) + { + /* Set E bit for next LI if present */ + if (index < num_li - 1) + RLC_SET_BIT(temp,li_bit_offset + RLC_AM_LI_BITS); + /* Set LI */ + RLC_AM_PDU_SET_LI(temp,new_li_list[index],li_bit_offset); + *pdu_segment_header_p = temp >> 8; + *(pdu_segment_header_p + 1) = temp & 0xFF; + pdu_segment_header_p += li_jump_offset; + li_bit_offset ^= 0x4; + li_jump_offset ^= 0x3; + + temp = ((*pdu_segment_header_p) << 8) | (*(pdu_segment_header_p + 1)); + index ++; + } + } + + /* copy data part */ + /* Fill mem_block contexts */ + ((struct mac_tb_ind *) (new_segment_p->data))->first_bit = 0; + ((struct mac_tb_ind *) (new_segment_p->data))->data_ptr = (uint8_t*)&new_segment_p->data[sizeof (mac_rlc_max_rx_header_size_t)]; + ((struct mac_tb_ind *) (new_segment_p->data))->size = data_length_to_copy + header_size; + memcpy(pdu_new_segment_info_p->payload,pdu_rx_info_p->payload + so_offset,data_length_to_copy); + } + + return new_segment_p; +} + +rlc_am_rx_pdu_status_t rlc_am_rx_list_handle_pdu_segment( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t* const rlc_pP, + mem_block_t* const tb_pP) +{ + rlc_am_pdu_info_t* pdu_rx_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info; + rlc_am_pdu_info_t* pdu_info_cursor_p = NULL; + rlc_am_pdu_info_t* pdu_info_previous_cursor_p = NULL; + mem_block_t* cursor_p = rlc_pP->receiver_buffer.head; + mem_block_t* previous_cursor_p = NULL; + mem_block_t* next_cursor_p = NULL; + uint16_t so_start_min = 0; + uint16_t so_end = 0; + uint16_t so_start_segment = pdu_rx_info_p->so; + uint16_t so_end_segment = pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1; + + /*****************************************************/ + // 1) Find previous cursor to the PDU to insert + /*****************************************************/ + AssertFatal(cursor_p != NULL,"AM Rx PDU Error, received buffer empty LcID=%d\n",rlc_pP->channel_id); + + do { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + + // Stop if Cursor SN >= Received SN + if (RLC_AM_DIFF_SN(pdu_info_cursor_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(pdu_rx_info_p->sn,rlc_pP->vr_r)) { + break; + } + + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + cursor_p = cursor_p->next; + } while (cursor_p != NULL); + + /*****************************************************/ + // 2) Store the received Segment + /*****************************************************/ + // First case : cursor_p is NULL or its SN is different from the received one, it means the SN is received for the first time + // Insert PDU after previous_cursor_p + if ((cursor_p == NULL) || (pdu_info_cursor_p->sn != pdu_rx_info_p->sn)) { + if (previous_cursor_p != NULL) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT SN=%d] PDU SEGMENT INSERTED AFTER PDU SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn, + pdu_info_previous_cursor_p->sn); + list2_insert_after_element(tb_pP, previous_cursor_p, &rlc_pP->receiver_buffer); + } + else { /* SN of head of Rx PDU list is higher than received PDU SN */ + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT SN=%d] PDU SEGMENT INSERTED BEFORE PDU SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn, + pdu_info_cursor_p->sn); + list2_insert_before_element(tb_pP, cursor_p, &rlc_pP->receiver_buffer); + } + + return RLC_AM_DATA_PDU_STATUS_OK; + } + + /********************************************/ + /* Now handle case cursor->sn = received SN */ + /********************************************/ + + rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + + // Filter out SN duplicate + if (pdu_cursor_mgnt_p->all_segments_received) { + return RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE; + } + + // Try to catch a segment duplicate + next_cursor_p = cursor_p; + while ((next_cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn)) { + if ((so_start_segment >= pdu_info_cursor_p->so) && (so_end_segment <= pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size - 1)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT] DISCARD : DUPLICATE SEGMENT SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn); + return RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE; + } + next_cursor_p = next_cursor_p->next; + if (next_cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + } + } + + // Reset pdu_info_cursor_p because of the loop before + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + + // Try to Handle the most likely cases first + if (pdu_info_cursor_p->so == 0) { + + /* Loop on stored segments and find the stored segment containing received SOStart */ + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + while ((cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) + && ((pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size) <= so_start_segment)) { + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + + // Most likely case : no duplicate, the segment is put after all stored segments which are contiguous + if ((cursor_p == NULL) || (pdu_info_cursor_p->sn != pdu_rx_info_p->sn) || (pdu_info_cursor_p->so > so_end_segment)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT SN=%d SOSTART=%d] PDU SEGMENT INSERTED AFTER PDU SEGMENT WITH SOEND=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn,so_start_segment, + pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size - 1); + + list2_insert_after_element(tb_pP, previous_cursor_p, &rlc_pP->receiver_buffer); + return RLC_AM_DATA_PDU_STATUS_OK; + } + + // Duplicate case : Resume contiguous scan and update previous_cursor_p + so_start_min = pdu_info_previous_cursor_p->so; + so_end = so_start_min + pdu_info_previous_cursor_p->payload_size; + cursor_p = previous_cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + while ((cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) + && (pdu_info_cursor_p->so == so_end)) { + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + so_end += pdu_info_cursor_p->payload_size; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + + /* Now discard the PDU segment if it is within so_start_min and so_end */ + if ((so_start_min <= so_start_segment) && (so_end_segment <= so_end - 1)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT] DISCARD : DUPLICATE SEGMENT SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn); + return RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE; + } + + // Discard potential embedded segments in the received PDU segment + // The first one is discontigous + next_cursor_p = cursor_p; + while ((next_cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && + (so_end_segment >= pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size - 1)) { + /* Discard the segment */ + cursor_p = next_cursor_p; + next_cursor_p = next_cursor_p->next; + list2_remove_element (cursor_p, &rlc_pP->receiver_buffer); + free_mem_block(cursor_p, __func__); + + if (next_cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + } + } + cursor_p = next_cursor_p; + + //Remove duplicate at the begining + if (so_start_segment < pdu_info_previous_cursor_p->so) { + so_start_segment = pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size; + } + else if (so_start_segment < pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size){ + so_start_segment += (pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size - so_start_segment); + } + + // Now remove duplicate at the end, only valid if cursor_p SN has the same received SN + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + + if ((pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && (so_end_segment >= pdu_info_cursor_p->so)) { + so_end_segment = pdu_info_cursor_p->so - 1; + } + } + + AssertFatal((so_start_segment <= so_end_segment) && (pdu_rx_info_p->so <= so_start_segment) && + (so_end_segment <= pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1), + " AM RX PDU Segment Duplicate elimination error FirstSO=0 OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d\n", + pdu_rx_info_p->so,pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1,so_start_segment,so_end_segment,pdu_rx_info_p->sn); + + } // end pdu_info_cursor_p->so == 0 + else { + // Handle most likely case : PDU Segment without duplicate is inserted before first stored PDU segment + if (so_end_segment < pdu_info_cursor_p->so) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT SN=%d SOSTART=%d SOEND=%d] PDU SEGMENT INSERTED BEFORE PDU SEGMENT WITH SOSTART=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn,so_start_segment,so_end_segment, + pdu_info_cursor_p->so); + + list2_insert_before_element(tb_pP, cursor_p, &rlc_pP->receiver_buffer); + return RLC_AM_DATA_PDU_STATUS_OK; + } + + // Handle duplicate case + if (so_start_segment < pdu_info_cursor_p->so) { + // First Case : only duplicate at the end + // Scan for embedded segments to be discarded + next_cursor_p = cursor_p; + while ((next_cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && + (so_end_segment >= pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size - 1)) { + /* Discard the segment */ + cursor_p = next_cursor_p; + next_cursor_p = next_cursor_p->next; + list2_remove_element (cursor_p, &rlc_pP->receiver_buffer); + free_mem_block(cursor_p, __func__); + + if (next_cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + } + } + cursor_p = next_cursor_p; + + // Now remove duplicate at the end, only valid if cursor_p SN has the same received SN + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + + if ((pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && (so_end_segment >= pdu_info_cursor_p->so)) { + so_end_segment = pdu_info_cursor_p->so - 1; + } + } + + AssertFatal((so_start_segment <= so_end_segment) && + (so_end_segment <= pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1), + " AM RX PDU Segment Duplicate elimination at the end error FirstSO!=0 SOStart=%d OldSOEnd=%d newSOEnd =%d SN=%d\n", + pdu_rx_info_p->so,pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1,so_end_segment,pdu_rx_info_p->sn); + + } + else { + // Second Case: Duplicate at the begining and potentially at the end + /* Loop on stored segments and find the stored segment containing received SOStart */ + + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + while ((cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) + && ((pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size) <= so_start_segment)) { + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + + // Most likely case : no duplicate, the segment is put after all stored segments which are contiguous + if ((cursor_p == NULL) || (pdu_info_cursor_p->sn != pdu_rx_info_p->sn) || (pdu_info_cursor_p->so > so_end_segment)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT SN=%d SOSTART=%d] PDU SEGMENT INSERTED AFTER PDU SEGMENT WITH SOEND=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn,so_start_segment, + pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size - 1); + + list2_insert_after_element(tb_pP, previous_cursor_p, &rlc_pP->receiver_buffer); + return RLC_AM_DATA_PDU_STATUS_OK; + } + + // Now look for contiguous segments to check whether the received segment is not fully duplicate + so_start_min = pdu_info_previous_cursor_p->so; + so_end = so_start_min + pdu_info_previous_cursor_p->payload_size; + cursor_p = previous_cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + while ((cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) + && (pdu_info_cursor_p->so == so_end)) { + previous_cursor_p = cursor_p; + pdu_info_previous_cursor_p = pdu_info_cursor_p; + so_end += pdu_info_cursor_p->payload_size; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + + /* Now discard the PDU segment if it is within so_start_min and so_end */ + if ((so_start_min <= so_start_segment) && (so_end_segment < so_end)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT] DISCARD : DUPLICATE SEGMENT SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn); + return RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE; + } + + //Remove duplicate at the begining + if (so_start_segment < pdu_info_previous_cursor_p->so) { + so_start_segment = pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size; + } + else if (so_start_segment < pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size){ + so_start_segment += (pdu_info_previous_cursor_p->so + pdu_info_previous_cursor_p->payload_size - so_start_segment); + } + + + // Now Scan for embedded segments to be discarded + next_cursor_p = cursor_p; + while ((next_cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && + (so_end_segment >= pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size - 1)) { + /* Discard the segment */ + cursor_p = next_cursor_p; + next_cursor_p = next_cursor_p->next; + list2_remove_element (cursor_p, &rlc_pP->receiver_buffer); + free_mem_block(cursor_p, __func__); + + if (next_cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + } + } + cursor_p = next_cursor_p; + + // Now remove duplicate at the end, only valid if cursor_p SN has the same received SN + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(next_cursor_p->data))->pdu_info; + + if ((pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && (so_end_segment >= pdu_info_cursor_p->so)) { + so_end_segment = pdu_info_cursor_p->so - 1; + } + } + + AssertFatal((so_start_segment <= so_end_segment) && (pdu_rx_info_p->so <= so_start_segment) && + (so_end_segment <= pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1), + " AM RX PDU Segment Duplicate elimination error FirstSO!=0 OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d\n", + pdu_rx_info_p->so,pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1,so_start_segment,so_end_segment,pdu_rx_info_p->sn); + } + + } // end pdu_info_cursor_p->so != 0 + + + /* Last step : duplicate bytes had been removed, build a new PDU segment */ + AssertFatal((pdu_rx_info_p->so != so_start_segment) || (so_end_segment != pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1), + " AM RX PDU Segment Duplicate elimination error FirstSO!=0 OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d\n", + pdu_rx_info_p->so,pdu_rx_info_p->so + pdu_rx_info_p->payload_size - 1,so_start_segment,so_end_segment,pdu_rx_info_p->sn); + + mem_block_t* trunc_segment = create_new_segment_from_pdu(tb_pP,so_start_segment - pdu_rx_info_p->so,so_end_segment - so_start_segment + 1); + if (trunc_segment != NULL) { + LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SEGMENT] CREATE SEGMENT FROM SEGMENT OFFSET=%d DATA LENGTH=%d SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),so_start_segment - pdu_rx_info_p->so,so_end_segment - so_start_segment + 1,pdu_rx_info_p->sn); + + if (previous_cursor_p != NULL) { + list2_insert_after_element(trunc_segment, previous_cursor_p, &rlc_pP->receiver_buffer); + } + else { + list2_insert_before_element(trunc_segment, rlc_pP->receiver_buffer.head, &rlc_pP->receiver_buffer); + } + + /* Free original PDU Segment */ + free_mem_block(tb_pP, __func__); + + return RLC_AM_DATA_PDU_STATUS_OK; + } + else { + return RLC_AM_DATA_PDU_STATUS_BUFFER_FULL; + } + +} + +rlc_am_rx_pdu_status_t rlc_am_rx_list_handle_pdu( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t* const rlc_pP, + mem_block_t* const tb_pP) +{ + rlc_am_pdu_info_t* pdu_rx_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info; + rlc_am_pdu_info_t* pdu_info_cursor_p = NULL; + mem_block_t* cursor_p = rlc_pP->receiver_buffer.head; + mem_block_t* previous_cursor_p = NULL; + rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK; + // it is assumed this pdu is in rx window + + + /*****************************************************/ + // 1) Find previous cursor to the PDU to insert + /*****************************************************/ + AssertFatal(cursor_p != NULL,"AM Rx PDU Error, received buffer empty LcID=%d\n",rlc_pP->channel_id); + + do { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + + // Stop if Cursor SN >= Received SN + if (RLC_AM_DIFF_SN(pdu_info_cursor_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(pdu_rx_info_p->sn,rlc_pP->vr_r)) { + break; + } + + previous_cursor_p = cursor_p; + cursor_p = cursor_p->next; + } while (cursor_p != NULL); + + /*****************************************************/ + // 2) Insert PDU by removing byte duplicate if required + /*****************************************************/ + // First case : cursor_p is NULL or SN are different, it means the SN is received for the first time + // Insert PDU after previous_cursor_p + if ((cursor_p == NULL) || (pdu_info_cursor_p->sn != pdu_rx_info_p->sn)) { + if (previous_cursor_p != NULL) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%d] PDU INSERTED AFTER PDU SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn, + ((rlc_am_rx_pdu_management_t*)(previous_cursor_p->data))->pdu_info.sn); + list2_insert_after_element(tb_pP, previous_cursor_p, &rlc_pP->receiver_buffer); + } + else { /* SN of head of Rx PDU list is higher than received PDU SN */ + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%d] PDU INSERTED BEFORE PDU SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn, + pdu_info_cursor_p->sn); + list2_insert_before_element(tb_pP, cursor_p, &rlc_pP->receiver_buffer); + } + + return pdu_status; + } + + // Filter out SN duplicate + // SN of received PDU has already data stored + rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); + + if (pdu_cursor_mgnt_p->all_segments_received) { + return RLC_AM_DATA_PDU_STATUS_SN_DUPLICATE; + } + + /* check if the received PDU is equal to vrR */ + if ((pdu_rx_info_p->sn != rlc_pP->vr_r) || (pdu_info_cursor_p->so != 0)) { + /* The full received PDU can replace the allready received PDU Segments. */ + /* clean them and append this PDU */ + mem_block_t* cursor_next_p = cursor_p; + while (cursor_next_p) { + cursor_p = cursor_next_p; + cursor_next_p = cursor_next_p->next; + list2_remove_element (cursor_p, &rlc_pP->receiver_buffer); + free_mem_block(cursor_p, __func__); + if (cursor_next_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_next_p->data))->pdu_info; + if (pdu_info_cursor_p->sn != pdu_rx_info_p->sn) { + break; + } + } + } + + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU REPLACES STORED PDU SEGMENTS SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_rx_info_p->sn); + + if (previous_cursor_p != NULL) { + list2_insert_after_element(tb_pP, previous_cursor_p, &rlc_pP->receiver_buffer); + } + else { + list2_insert_before_element(tb_pP, cursor_next_p, &rlc_pP->receiver_buffer); + } + + return pdu_status; + } // End SN != vrR or SO != 0 + else { + /* First update cursor until discontinuity */ + previous_cursor_p = cursor_p; + AssertFatal(pdu_info_cursor_p->rf != 0,"AM Rx PDU Error, stored SN=%d should be a PDU segment\n",pdu_info_cursor_p->sn); + AssertFatal(((rlc_am_rx_pdu_management_t *) (cursor_p->data))->all_segments_received == 0, + "AM Rx PDU Error, stored SN=%d already fully received\n",pdu_info_cursor_p->sn); + sdu_size_t next_waited_so = 0; + while ((cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn) && (pdu_info_cursor_p->so == next_waited_so)) { + next_waited_so += pdu_info_cursor_p->payload_size; + previous_cursor_p = cursor_p; + cursor_p = cursor_p->next; + if (cursor_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + } + /* Create a new PDU segment by removing first next_waited_so bytes */ + mem_block_t* trunc_pdu = create_new_segment_from_pdu(tb_pP,next_waited_so,pdu_rx_info_p->payload_size - next_waited_so); + + if (trunc_pdu != NULL) { + /* Insert PDU Segment */ + list2_insert_after_element(trunc_pdu, previous_cursor_p, &rlc_pP->receiver_buffer); + + LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] CREATE PDU SEGMENT FROM PDU OFFSET =%d SN=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),next_waited_so,pdu_rx_info_p->sn); + + /* clean previous stored segments in duplicate */ + if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == pdu_rx_info_p->sn)) { + mem_block_t* cursor_next_p = cursor_p; + while (cursor_next_p) { + cursor_p = cursor_next_p; + cursor_next_p = cursor_next_p->next; + list2_remove_element (cursor_p, &rlc_pP->receiver_buffer); + free_mem_block(cursor_p, __func__); + if (cursor_next_p != NULL) { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_next_p->data))->pdu_info; + if (pdu_info_cursor_p->sn != pdu_rx_info_p->sn) { + break; + } + } + } + } + + /* Free original PDU */ + free_mem_block(tb_pP, __func__); + + return pdu_status; + } + else { + return RLC_AM_DATA_PDU_STATUS_BUFFER_FULL; + } + } +} +// returns 0 if success +// returns neg value if failure +//----------------------------------------------------------------------------- +rlc_am_rx_pdu_status_t +rlc_am_rx_list_check_duplicate_insert_pdu( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t* const rlc_pP, + mem_block_t* const tb_pP) +{ + rlc_am_pdu_info_t* pdu_rx_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info; + mem_block_t* cursor_p = NULL; + cursor_p = rlc_pP->receiver_buffer.head; + rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK; + // it is assumed this pdu is in rx window + + /* Init Reassembly status */ + ((rlc_am_rx_pdu_management_t*)(tb_pP->data))->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO; + + if (cursor_p == NULL) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[INSERT PDU] LINE %d RX PDU SN %04d (only inserted)\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + pdu_rx_info_p->sn); + list2_add_head(tb_pP, &rlc_pP->receiver_buffer); + return pdu_status; + } + + + if (pdu_rx_info_p->rf == 0) { // Case normal PDU received + pdu_status = rlc_am_rx_list_handle_pdu(ctxt_pP,rlc_pP,tb_pP); + } + else { + pdu_status = rlc_am_rx_list_handle_pdu_segment(ctxt_pP,rlc_pP,tb_pP); + } + + return pdu_status; +} +#if 0 // returns 0 if success // returns neg value if failure //----------------------------------------------------------------------------- @@ -49,6 +854,10 @@ rlc_am_rx_list_insert_pdu( cursor_p = rlc_pP->receiver_buffer.head; // it is assumed this pdu is in rx window + //TODO : check for duplicate + // should be rewrite + /* look for previous SN */ + if (cursor_p) { if (rlc_pP->vr_mr < rlc_pP->vr_r) { if (pdu_info_p->sn >= rlc_pP->vr_r) { @@ -479,6 +1288,8 @@ rlc_am_rx_list_insert_pdu( pdu_info_p->sn); return -1; } +#endif + //----------------------------------------------------------------------------- void rlc_am_rx_check_all_byte_segments( @@ -519,8 +1330,10 @@ rlc_am_rx_check_all_byte_segments( // in case all first segments up to tb_pP are in list // the so field of the first PDU should be 0 //cursor_p = list.head; + //we start from the first stored PDU segment of this SN pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + // if the first segment does not have SO = 0 then no need to continue if (pdu_info_p->so != 0) { return; } @@ -549,13 +1362,15 @@ rlc_am_rx_check_all_byte_segments( next_waited_so = next_waited_so + pdu_info_p->payload_size; //msg("rlc_am_rx_check_all_byte_segments(%d) @6\n",sn); } else { // assumed pdu_info_p->so + pdu_info_p->payload_size > next_waited_so - next_waited_so = (next_waited_so + pdu_info_p->payload_size) - (next_waited_so - pdu_info_p->so); + //next_waited_so = (next_waited_so + pdu_info_p->payload_size) - (next_waited_so - pdu_info_p->so); //msg("rlc_am_rx_check_all_byte_segments(%d) @7\n",sn); + return; } if (pdu_info_p->lsf > 0) { //msg("rlc_am_rx_check_all_byte_segments(%d) @8\n",sn); rlc_am_rx_mark_all_segments_received(ctxt_pP, rlc_pP, first_cursor_p); + return; } } @@ -599,13 +1414,15 @@ rlc_am_rx_mark_all_segments_received( } } //----------------------------------------------------------------------------- +//#define RLC_AM_DEBUG_REASSEMBLY void rlc_am_rx_list_reassemble_rlc_sdus( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP) { - mem_block_t* cursor_p = NULL; - rlc_am_rx_pdu_management_t* rlc_am_rx_old_pdu_management = NULL; + mem_block_t* cursor_p = NULL; + rlc_am_rx_pdu_management_t* rlc_am_rx_old_pdu_management = NULL; + rlc_am_pdu_info_t* pdu_info_p = NULL; cursor_p = list2_get_head(&rlc_pP->receiver_buffer); @@ -614,20 +1431,79 @@ rlc_am_rx_list_reassemble_rlc_sdus( } rlc_am_rx_pdu_management_t* rlc_am_rx_pdu_management_p = ((rlc_am_rx_pdu_management_t*)(cursor_p->data)); + pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; +#ifdef RLC_AM_DEBUG_REASSEMBLY + rlc_usn_t sn_reass_start = pdu_info_p->sn; +#endif + + /* Specific process for the first SN if all PDU segments had been reassembled but not freed */ + if ((rlc_am_rx_pdu_management_p->all_segments_received > 0) && (pdu_info_p->rf != 0)) { + rlc_sn_t sn = pdu_info_p->sn; + while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLED) + && ((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.sn == sn) { + cursor_p = list2_remove_head(&rlc_pP->receiver_buffer); + free_mem_block(cursor_p, __func__); + cursor_p = list2_get_head(&rlc_pP->receiver_buffer); + } + + /* Reset Management pointers */ + if (cursor_p != NULL) { + rlc_am_rx_pdu_management_p = ((rlc_am_rx_pdu_management_t*)(cursor_p->data)); + /* Next SN must be the same or SN+1 */ + if (RLC_AM_DIFF_SN(rlc_am_rx_pdu_management_p->pdu_info.sn,sn) > 1) { + return; + } + } + else { + return; + } + } do { if (rlc_am_rx_pdu_management_p->all_segments_received > 0) { cursor_p = list2_remove_head(&rlc_pP->receiver_buffer); - rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p); + rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p,TRUE); rlc_am_rx_old_pdu_management = rlc_am_rx_pdu_management_p; cursor_p = list2_get_head(&rlc_pP->receiver_buffer); if (cursor_p == NULL) { +#ifdef RLC_AM_DEBUG_REASSEMBLY + LOG_D(RLC, "RLC AM REASSEMBLY from sn=%d to ALL, vrR=%d vrMS=%d\n", + sn_reass_start,rlc_pP->vr_r,rlc_pP->vr_ms); +#endif return; } rlc_am_rx_pdu_management_p = ((rlc_am_rx_pdu_management_t*)(cursor_p->data)); - } else { + } + else if (rlc_am_rx_pdu_management_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING) { + rlc_am_rx_pdu_management_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLED; + + rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p,FALSE); + rlc_am_rx_old_pdu_management = rlc_am_rx_pdu_management_p; + cursor_p = cursor_p->next; + + if (cursor_p == NULL) { +#ifdef RLC_AM_DEBUG_REASSEMBLY + LOG_D(RLC, "RLC AM REASSEMBLY from sn=%d to ALL, Last is Segment, vrR=%d vrMS=%d\n", + sn_reass_start,rlc_pP->vr_r,rlc_pP->vr_ms); +#endif + return; + } + + rlc_am_rx_pdu_management_p = ((rlc_am_rx_pdu_management_t*)(cursor_p->data)); + } + else if (rlc_am_rx_pdu_management_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLED) { + rlc_am_rx_old_pdu_management = rlc_am_rx_pdu_management_p; + cursor_p = cursor_p->next; + + if (cursor_p == NULL) { + return; + } + + rlc_am_rx_pdu_management_p = ((rlc_am_rx_pdu_management_t*)(cursor_p->data)); + } + else { #if RLC_STOP_ON_LOST_PDU if (list2_get_head(&rlc_pP->receiver_buffer) != cursor_p) { @@ -637,11 +1513,28 @@ rlc_am_rx_list_reassemble_rlc_sdus( } #endif +#ifdef RLC_AM_DEBUG_REASSEMBLY + LOG_D(RLC, "RLC AM REASSEMBLY from sn=%d to ALL, vrR=%d vrMS=%d\n", + sn_reass_start,rlc_pP->vr_r,rlc_pP->vr_ms); +#endif + return; + } + + } while (((RLC_AM_DIFF_SN(rlc_am_rx_pdu_management_p->pdu_info.sn,rlc_am_rx_old_pdu_management->pdu_info.sn) < 2) && (rlc_am_rx_old_pdu_management->all_segments_received > 0)) + || ((rlc_am_rx_pdu_management_p->pdu_info.sn == rlc_am_rx_old_pdu_management->pdu_info.sn) && (rlc_am_rx_pdu_management_p->segment_reassembled != RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO))); + +#ifdef RLC_AM_DEBUG_REASSEMBLY + mem_block_t* cursor_head_p = list2_get_head(&rlc_pP->receiver_buffer); + if (cursor_head_p == NULL) { return; } - } while ((rlc_am_rx_pdu_management_p->pdu_info.sn == ((rlc_am_rx_old_pdu_management->pdu_info.sn + 1) & RLC_AM_SN_MASK)) - || ((rlc_am_rx_pdu_management_p->pdu_info.sn == rlc_am_rx_old_pdu_management->pdu_info.sn) && (rlc_am_rx_pdu_management_p->all_segments_received > 0))); + rlc_am_pdu_info_t* pdu_info_head_p = &((rlc_am_rx_pdu_management_t*)(cursor_head_p->data))->pdu_info; + + LOG_D(RLC, "RLC AM REASSEMBLY from sn=%d to sn=%d, next_sn=%d head sn=%d vrR=%d vrMS=%d\n", + sn_reass_start,rlc_am_rx_old_pdu_management->pdu_info.sn,rlc_am_rx_pdu_management_p->pdu_info.sn,pdu_info_head_p->sn,rlc_pP->vr_r,rlc_pP->vr_ms); +#endif + } //----------------------------------------------------------------------------- mem_block_t * diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h index c75255c4fac76e605bc84d911baa0cf587b6d970..e6e043dd0a579092223189ba1464519bc931be15 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h @@ -59,6 +59,16 @@ #include "PHY/defs.h" //----------------------------------------------------------------------------- +/*! \fn rlc_am_rx_pdu_status_t rlc_am_rx_list_check_duplicate_insert_pdu(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,mem_block_t* const tb_pP) +* \brief Insert a PDU in the RX buffer after removing byte duplicate (implemented with a list). +* \param[in] ctxt_pP Running context. +* \param[in] rlcP RLC AM protocol instance pointer. +* \param[in] tbP A PDU embedded in a mem_block_t. +* \return Zero if the PDU could be inserted in the RX buffer, a negative value if the PDU could not be inserted. +*/ +protected_rlc_am_rx_list( rlc_am_rx_pdu_status_t rlc_am_rx_list_check_duplicate_insert_pdu(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,mem_block_t* const tb_pP);) + +#if 0 /*! \fn signed int rlc_am_rx_list_insert_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP , mem_block_t* const tbP) * \brief Insert a PDU in the RX buffer (implemented with a list). * \param[in] ctxt_pP Running context. @@ -67,6 +77,15 @@ * \return Zero if the PDU could be inserted in the RX buffer, a negative value if the PDU could not be inserted. */ protected_rlc_am_rx_list( signed int rlc_am_rx_list_insert_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP);) +#endif + +/*! \fn boolean_t rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP) +* \brief Check if reassembly taking into account potential new vrR value +* \param[in] ctxt_pP Running context. +* \param[in] rlcP RLC AM protocol instance pointer. +* \return TRUE if reassembly must be done, FALSE else +*/ +protected_rlc_am_rx_list( boolean_t rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP);) /*! \fn void rlc_am_rx_check_all_byte_segments(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP) * \brief Check if all sub-segments of a PDU are received, if yes then call rlc_am_rx_mark_all_segments_received() procedure. diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c index 893588d65e28fbc7651b7ef36bfec7e424309a67..113ee7d048a61677c67fac3d7f818dde03b3374b 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c @@ -39,7 +39,8 @@ void rlc_am_pdu_polling ( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlc_pP, rlc_am_pdu_sn_10_t *const pdu_pP, - const int16_t payload_sizeP) + const int16_t payload_sizeP, + boolean_t is_new_pdu) { // 5.2.2 Polling // An AM RLC entity can poll its peer AM RLC entity in order to trigger STATUS reporting at the peer AM RLC entity. @@ -68,49 +69,59 @@ void rlc_am_pdu_polling ( // - start t-PollRetransmit; // - else: // - restart t-PollRetransmit; - rlc_pP->c_pdu_without_poll += 1; - rlc_pP->c_byte_without_poll += payload_sizeP; + + if (is_new_pdu) { + if (rlc_pP->poll_pdu != RLC_AM_POLL_PDU_INFINITE) { + rlc_pP->c_pdu_without_poll += 1; + } + + if (rlc_pP->poll_byte != RLC_AM_POLL_BYTE_INFINITE) { + rlc_pP->c_byte_without_poll += payload_sizeP; + } + } if ( - (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) || - (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte) || + ((is_new_pdu) && ((rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) || + (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte))) || ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) || (rlc_pP->vt_s == rlc_pP->vt_ms) || - (rlc_pP->force_poll == TRUE) + (rlc_pP->force_poll == true) ) { - rlc_pP->force_poll = FALSE; + rlc_pP->force_poll = false; - if (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) { + if ((is_new_pdu) && (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu)) { LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX NUM PDU THRESHOLD %d HAS BEEN REACHED\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->poll_pdu); - } else - if (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte) { + } + if ((is_new_pdu) && (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte)) { LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX NUM BYTES THRESHOLD %d HAS BEEN REACHED\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->poll_byte); - } else + } if ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) { LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX BUFFERS ARE EMPTY\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); - } else + } if (rlc_pP->vt_s == rlc_pP->vt_ms) { LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE OF WINDOW STALLING\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); } - pdu_pP->b1 = pdu_pP->b1 | 0x20; + RLC_AM_PDU_SET_POLL(pdu_pP->b1); rlc_pP->c_pdu_without_poll = 0; rlc_pP->c_byte_without_poll = 0; - rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK; + // vt_s shall have been updated before in case of new transmission + rlc_pP->poll_sn = RLC_AM_PREV_SN(rlc_pP->vt_s); //optimisation if (!rlc_pP->t_poll_retransmit.running) { rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP); //optimisation } else { //optimisation rlc_pP->t_poll_retransmit.frame_time_out = ctxt_pP->frame + rlc_pP->t_poll_retransmit.time_out; //optimisation } } else { - pdu_pP->b1 = pdu_pP->b1 & 0xDF; + // Need to clear poll bit as it may be a copy(retransmission case) of the original RLC PDU which was containing a poll + RLC_AM_PDU_CLEAR_POLL(pdu_pP->b1); } } //----------------------------------------------------------------------------- @@ -178,7 +189,9 @@ void rlc_am_segment_10 ( if (rlc_pP->nb_sdu_no_segmented <= 1) { max_li_overhead = 0; } else { - max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2); + /* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/ + test_num_li = rlc_pP->nb_sdu_no_segmented - 1; + max_li_overhead = test_num_li + (test_num_li >> 1) + (test_num_li & 1); } LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] max_li_overhead %d\n", @@ -210,7 +223,7 @@ void rlc_am_segment_10 ( pdu_remaining_size = data_pdu_size - RLC_AM_HEADER_MIN_SIZE; pdu_p = (rlc_am_pdu_sn_10_t*) (&pdu_mem_p->data[sizeof(struct mac_tb_req)]); pdu_tb_req_p = (struct mac_tb_req*) (pdu_mem_p->data); - pdu_mngt_p = &rlc_pP->pdu_retrans_buffer[rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE]; + pdu_mngt_p = &rlc_pP->tx_data_pdu_buffer[rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE]; memset(pdu_mngt_p, 0, sizeof (rlc_am_tx_data_pdu_management_t)); memset (pdu_mem_p->data, 0, sizeof (rlc_am_pdu_sn_10_t)+sizeof(struct mac_tb_req)); @@ -485,11 +498,11 @@ void rlc_am_segment_10 ( fi = fi + 1; } - pdu_p->b1 = pdu_p->b1 | (fi << 3); + pdu_p->b1 = pdu_p->b1 | (fi << RLC_AM_PDU_FI_OFFSET); // set fist e bit if (fill_num_li > 0) { - pdu_p->b1 = pdu_p->b1 | 0x04; + RLC_AM_PDU_SET_E(pdu_p->b1); } LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] SEND PDU SN %04d SIZE %d BYTES PAYLOAD SIZE %d BYTES\n", @@ -501,8 +514,9 @@ void rlc_am_segment_10 ( rlc_pP->stat_tx_data_pdu += 1; rlc_pP->stat_tx_data_bytes += (data_pdu_size - pdu_remaining_size); - //pdu_p->sn = rlc_pP->vt_s; - pdu_p->b1 = pdu_p->b1 | 0x80; // DATA/CONTROL field is DATA PDU + // set DATA/CONTROL field is DATA PDU(1) + RLC_AM_PDU_SET_D_C(pdu_p->b1); + // set sn = rlc_pP->vt_s; pdu_p->b1 = pdu_p->b1 | (rlc_pP->vt_s >> 8); pdu_p->b2 = rlc_pP->vt_s & 0xFF; rlc_pP->vt_s = (rlc_pP->vt_s+1) & RLC_AM_SN_MASK; @@ -511,24 +525,28 @@ void rlc_am_segment_10 ( pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size; //#warning "why 3000: changed to RLC_SDU_MAX_SIZE " assert(pdu_tb_req_p->tb_size < RLC_SDU_MAX_SIZE ); - rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt_p->payload_size); + rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt_p->payload_size,true); //list_add_tail_eurecom (pdu_mem_p, &rlc_pP->segmentation_pdu_list); pdu_mngt_p->mem_block = pdu_mem_p; pdu_mngt_p->first_byte = (unsigned char*)pdu_p; pdu_mngt_p->header_and_payload_size = data_pdu_size - pdu_remaining_size; - pdu_mngt_p->retx_count = -1; + pdu_mngt_p->retx_count = 0; + pdu_mngt_p->retx_count_next = 0; + pdu_mngt_p->flags.retransmit = 0; + pdu_mngt_p->flags.transmitted = 1; + pdu_mngt_p->sn = RLC_AM_PREV_SN(rlc_pP->vt_s); - rlc_pP->retrans_num_pdus += 1; - rlc_pP->retrans_num_bytes += pdu_mngt_p->header_and_payload_size; + //TBC: What for resetting local pointers at the end ?? pdu_p = NULL; pdu_mem_p = NULL; //nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size; nb_bytes_to_transmit = 0; // 1 PDU only - mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, (rlc_pP->vt_s-1) & RLC_AM_SN_MASK); + /* We need to copy the PDU to pass to MAC in order to keep it in the buffer for potential retransmissions */ + mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, RLC_AM_PREV_SN(rlc_pP->vt_s)); list_add_tail_eurecom (copy, &rlc_pP->segmentation_pdu_list); } diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h index 6b67758b80bd81a89f7467c50b45e01fbad63122..b52b3e5aaa5d87e78b413e911504df7aa337f030 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h @@ -51,14 +51,14 @@ # endif # endif -/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP) +/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP,boolean_t is_new_pdu) * \brief Set or not the poll bit in the PDU header depending on RLC AM protocol variables. * \param[in] ctxt_pP Running context. * \param[in] rlcP RLC AM protocol instance pointer. * \param[in] pduP Pointer on the header of the PDU in order to be able to set the poll bit if necessary. * \param[in] payload_sizeP Size of the payload of the PDU. */ -protected_rlc_am_segment(void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP);) +protected_rlc_am_segment(void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP,boolean_t is_new_pdu);) /*! \fn void rlc_am_segment_10 (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP) * \brief Segment a PDU with 10 bits sequence number, based on segmentation information given by MAC (size to transmit). diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.c index 37e9b13508e9fd133e068aa6e89ec01e3d4717a6..46a656e65a5961058625c4b973659ab729f21595 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.c @@ -19,6 +19,7 @@ * contact@openairinterface.org */ +#if 0 #define RLC_AM_MODULE 1 #define RLC_AM_SEGMENT_HOLES_C 1 //----------------------------------------------------------------------------- @@ -32,7 +33,7 @@ void rlc_am_clear_holes ( rlc_am_entity_t *const rlc_pP, const rlc_sn_t snP) { - rlc_pP->pdu_retrans_buffer[snP].num_holes = 0; + rlc_pP->tx_data_pdu_buffer[snP].num_holes = 0; } //----------------------------------------------------------------------------- void rlc_am_shift_down_holes ( @@ -43,12 +44,12 @@ void rlc_am_shift_down_holes ( { int i; - for (i=indexP; i < rlc_pP->pdu_retrans_buffer[snP].num_holes - 1; i++) { - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i] = rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i+1]; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i] = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i+1]; + for (i=indexP; i < rlc_pP->tx_data_pdu_buffer[snP].num_holes - 1; i++) { + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i+1]; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i+1]; } - rlc_pP->pdu_retrans_buffer[snP].num_holes = rlc_pP->pdu_retrans_buffer[snP].num_holes - 1; + rlc_pP->tx_data_pdu_buffer[snP].num_holes = rlc_pP->tx_data_pdu_buffer[snP].num_holes - 1; } //----------------------------------------------------------------------------- void rlc_am_shift_up_holes ( @@ -60,13 +61,13 @@ void rlc_am_shift_up_holes ( // shift include indexP int i; - for (i=rlc_pP->pdu_retrans_buffer[snP].num_holes; i > indexP; i--) { - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i] = rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i-1]; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i] = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i-1]; + for (i=rlc_pP->tx_data_pdu_buffer[snP].num_holes; i > indexP; i--) { + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i-1]; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i-1]; } - rlc_pP->pdu_retrans_buffer[snP].num_holes = rlc_pP->pdu_retrans_buffer[snP].num_holes + 1; - assert(rlc_pP->pdu_retrans_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); + rlc_pP->tx_data_pdu_buffer[snP].num_holes = rlc_pP->tx_data_pdu_buffer[snP].num_holes + 1; + assert(rlc_pP->tx_data_pdu_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); } //----------------------------------------------------------------------------- void rlc_am_remove_hole ( @@ -79,81 +80,81 @@ void rlc_am_remove_hole ( int i; #if TRACE_RLC_AM_HOLE LOG_D(RLC, - PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] REMOVE HOLE SN %04d so_startP %05d so_stopP %05d rlc_pP->pdu_retrans_buffer[snP].nack_so_start %05d rlc_pP->pdu_retrans_buffer[snP].nack_so_stop %05d\n", + PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] REMOVE HOLE SN %04d so_startP %05d so_stopP %05d rlc_pP->tx_data_pdu_buffer[snP].nack_so_start %05d rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop %05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, so_startP, so_stopP, - rlc_pP->pdu_retrans_buffer[snP].nack_so_start, - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop); + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start, + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop); #endif assert(so_startP <= so_stopP); - if (rlc_pP->pdu_retrans_buffer[snP].num_holes == 0) { - assert(so_startP == rlc_pP->pdu_retrans_buffer[snP].nack_so_start); - assert(so_stopP <= rlc_pP->pdu_retrans_buffer[snP].nack_so_stop); + if (rlc_pP->tx_data_pdu_buffer[snP].num_holes == 0) { + assert(so_startP == rlc_pP->tx_data_pdu_buffer[snP].nack_so_start); + assert(so_stopP <= rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop); #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] REMOVE HOLE SN %04d MODIFIED nack_so_start %05d->%05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, - rlc_pP->pdu_retrans_buffer[snP].nack_so_start, + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start, so_stopP+1); #endif - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = so_stopP+1; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = so_stopP+1; - if (rlc_pP->pdu_retrans_buffer[snP].nack_so_start >= rlc_pP->pdu_retrans_buffer[snP].nack_so_stop) { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = 0; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = 0x7FFF; + if (rlc_pP->tx_data_pdu_buffer[snP].nack_so_start >= rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop) { + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = 0; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = 0x7FFF; } } else { // normally should be removed in increasing order... - for (i = 0; i < rlc_pP->pdu_retrans_buffer[snP].num_holes; i++) { - if (so_startP <= rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i]) { - if (so_stopP >= rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i]) { + for (i = 0; i < rlc_pP->tx_data_pdu_buffer[snP].num_holes; i++) { + if (so_startP <= rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i]) { + if (so_stopP >= rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i]) { rlc_am_shift_down_holes(ctxt_pP, rlc_pP, snP, i); i = i - 1; } else { - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i] = so_stopP; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i] = so_stopP; - if (rlc_pP->pdu_retrans_buffer[snP].num_holes == 0) { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = 0; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = 0x7FFF; + if (rlc_pP->tx_data_pdu_buffer[snP].num_holes == 0) { + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = 0; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = 0x7FFF; } else { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = rlc_pP->pdu_retrans_buffer[snP].hole_so_start[0]; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[rlc_pP->pdu_retrans_buffer[snP].num_holes - 1]; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[0]; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[rlc_pP->tx_data_pdu_buffer[snP].num_holes - 1]; } #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] REMOVE HOLE SN %04d NOW nack_so_start %05d nack_so_stop %05d num holes %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, - rlc_pP->pdu_retrans_buffer[snP].nack_so_start, - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop, - rlc_pP->pdu_retrans_buffer[snP].num_holes); + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start, + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop, + rlc_pP->tx_data_pdu_buffer[snP].num_holes); #endif return; } - } else if (so_startP > rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i]) { - if (so_startP <= rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i]) { - if (so_stopP < rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i]) { + } else if (so_startP > rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i]) { + if (so_startP <= rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i]) { + if (so_stopP < rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i]) { // BAD CASE: 1 HOLE IS SPLITTED IN 2 HOLES rlc_am_shift_up_holes(ctxt_pP, rlc_pP, snP, i+1); - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i+1] = so_startP+1; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i+1] = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i]; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i] = so_startP - 1; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i+1] = so_startP+1; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i+1] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i]; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i] = so_startP - 1; } else { - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i] = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i] = so_startP; } } } } - if (rlc_pP->pdu_retrans_buffer[snP].num_holes == 0) { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = 0; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = 0x7FFF; + if (rlc_pP->tx_data_pdu_buffer[snP].num_holes == 0) { + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = 0; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = 0x7FFF; } else { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = rlc_pP->pdu_retrans_buffer[snP].hole_so_start[0]; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[rlc_pP->pdu_retrans_buffer[snP].num_holes - 1]; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[0]; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[rlc_pP->tx_data_pdu_buffer[snP].num_holes - 1]; } } @@ -161,11 +162,11 @@ void rlc_am_remove_hole ( LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] REMOVE HOLE SN %04d NOW nack_so_start %05d nack_so_stop %05d num holes %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, - rlc_pP->pdu_retrans_buffer[snP].nack_so_start, - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop, - rlc_pP->pdu_retrans_buffer[snP].num_holes); + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start, + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop, + rlc_pP->tx_data_pdu_buffer[snP].num_holes); #endif - assert(rlc_pP->pdu_retrans_buffer[snP].nack_so_start < rlc_pP->pdu_retrans_buffer[snP].payload_size); + assert(rlc_pP->tx_data_pdu_buffer[snP].nack_so_start < rlc_pP->tx_data_pdu_buffer[snP].payload_size); } //----------------------------------------------------------------------------- void rlc_am_get_next_hole ( @@ -175,9 +176,9 @@ void rlc_am_get_next_hole ( sdu_size_t* const so_startP, sdu_size_t* const so_stopP) { - if (rlc_pP->pdu_retrans_buffer[snP].num_holes == 0) { - *so_startP = rlc_pP->pdu_retrans_buffer[snP].nack_so_start; - *so_stopP = rlc_pP->pdu_retrans_buffer[snP].nack_so_stop; + if (rlc_pP->tx_data_pdu_buffer[snP].num_holes == 0) { + *so_startP = rlc_pP->tx_data_pdu_buffer[snP].nack_so_start; + *so_stopP = rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop; #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] rlc_am_get_next_hole(SN %04d) %05d->%05d (NUM HOLES == 0)\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), @@ -186,15 +187,15 @@ void rlc_am_get_next_hole ( *so_stopP); #endif } else { - *so_startP = rlc_pP->pdu_retrans_buffer[snP].hole_so_start[0]; - *so_stopP = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[0]; + *so_startP = rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[0]; + *so_stopP = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[0]; #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] rlc_am_get_next_hole(SN %04d) %05d->%05d (NUM HOLES == %d)\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, *so_startP, *so_stopP, - rlc_pP->pdu_retrans_buffer[snP].num_holes); + rlc_pP->tx_data_pdu_buffer[snP].num_holes); #endif } } @@ -214,33 +215,33 @@ void rlc_am_add_hole ( // if global NACK - if ((so_startP == 0) && ((so_stopP == 0x7FFF) || (so_stopP == rlc_pP->pdu_retrans_buffer[snP].payload_size - 1))) { - rlc_pP->pdu_retrans_buffer[snP].num_holes = 0; - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = so_startP; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = so_stopP; + if ((so_startP == 0) && ((so_stopP == 0x7FFF) || (so_stopP == rlc_pP->tx_data_pdu_buffer[snP].payload_size - 1))) { + rlc_pP->tx_data_pdu_buffer[snP].num_holes = 0; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = so_stopP; #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] SN %04d GLOBAL NACK 0->%05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP, so_stopP); #endif - assert(rlc_pP->pdu_retrans_buffer[snP].nack_so_start < rlc_pP->pdu_retrans_buffer[snP].payload_size); + assert(rlc_pP->tx_data_pdu_buffer[snP].nack_so_start < rlc_pP->tx_data_pdu_buffer[snP].payload_size); return; } if (so_stopP == 0x7FFF) { - so_stopP = rlc_pP->pdu_retrans_buffer[snP].payload_size - 1; + so_stopP = rlc_pP->tx_data_pdu_buffer[snP].payload_size - 1; } // first hole - if (rlc_pP->pdu_retrans_buffer[snP].num_holes == 0) { - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[0] = so_startP; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop [0] = so_stopP; + if (rlc_pP->tx_data_pdu_buffer[snP].num_holes == 0) { + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[0] = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop [0] = so_stopP; - rlc_pP->pdu_retrans_buffer[snP].num_holes = 1; + rlc_pP->tx_data_pdu_buffer[snP].num_holes = 1; - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = so_startP; - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = so_stopP; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = so_stopP; #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] FIRST HOLE SN %04d GLOBAL NACK %05d->%05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), @@ -248,44 +249,44 @@ void rlc_am_add_hole ( so_startP, so_stopP); #endif - assert(rlc_pP->pdu_retrans_buffer[snP].nack_so_start < rlc_pP->pdu_retrans_buffer[snP].payload_size); + assert(rlc_pP->tx_data_pdu_buffer[snP].nack_so_start < rlc_pP->tx_data_pdu_buffer[snP].payload_size); return; } hole_index = 0; - while (hole_index < rlc_pP->pdu_retrans_buffer[snP].num_holes) { - if (so_stopP < rlc_pP->pdu_retrans_buffer[snP].hole_so_start[hole_index]) { - assert(rlc_pP->pdu_retrans_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); + while (hole_index < rlc_pP->tx_data_pdu_buffer[snP].num_holes) { + if (so_stopP < rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[hole_index]) { + assert(rlc_pP->tx_data_pdu_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); if (hole_index > 0) { - assert(so_startP > rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[hole_index-1]); + assert(so_startP > rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[hole_index-1]); } - for (i=rlc_pP->pdu_retrans_buffer[snP].num_holes; i >= hole_index; i--) { - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i] = rlc_pP->pdu_retrans_buffer[snP].hole_so_start[i-1]; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i] = rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[i-1]; + for (i=rlc_pP->tx_data_pdu_buffer[snP].num_holes; i >= hole_index; i--) { + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[i-1]; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i] = rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[i-1]; } - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[hole_index] = so_startP; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[hole_index] = so_stopP; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[hole_index] = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[hole_index] = so_stopP; // update nack "window" vars nack_so_start, nack_so_stop if (hole_index == 0) { - rlc_pP->pdu_retrans_buffer[snP].nack_so_start = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_start = so_startP; } - rlc_pP->pdu_retrans_buffer[snP].num_holes += 1; + rlc_pP->tx_data_pdu_buffer[snP].num_holes += 1; #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] INSERT %d th HOLE SN %04d GLOBAL NACK %05d->%05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->pdu_retrans_buffer[snP].num_holes, + rlc_pP->tx_data_pdu_buffer[snP].num_holes, snP, so_startP, so_stopP); #endif - assert(rlc_pP->pdu_retrans_buffer[snP].nack_so_start < rlc_pP->pdu_retrans_buffer[snP].payload_size); - assert(rlc_pP->pdu_retrans_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); + assert(rlc_pP->tx_data_pdu_buffer[snP].nack_so_start < rlc_pP->tx_data_pdu_buffer[snP].payload_size); + assert(rlc_pP->tx_data_pdu_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); return; } @@ -293,17 +294,17 @@ void rlc_am_add_hole ( } // if here insert to the "tail" - if (so_startP > rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[hole_index - 1]) { - assert(rlc_pP->pdu_retrans_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); - rlc_pP->pdu_retrans_buffer[snP].hole_so_start[hole_index] = so_startP; - rlc_pP->pdu_retrans_buffer[snP].hole_so_stop[hole_index] = so_stopP; - rlc_pP->pdu_retrans_buffer[snP].num_holes += 1; + if (so_startP > rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[hole_index - 1]) { + assert(rlc_pP->tx_data_pdu_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); + rlc_pP->tx_data_pdu_buffer[snP].hole_so_start[hole_index] = so_startP; + rlc_pP->tx_data_pdu_buffer[snP].hole_so_stop[hole_index] = so_stopP; + rlc_pP->tx_data_pdu_buffer[snP].num_holes += 1; // update nack "window" vars nack_so_start, nack_so_stop - rlc_pP->pdu_retrans_buffer[snP].nack_so_stop = so_stopP; + rlc_pP->tx_data_pdu_buffer[snP].nack_so_stop = so_stopP; #if TRACE_RLC_AM_HOLE LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] INSERT THE %d th LAST HOLE SN %04d GLOBAL NACK %05d->%05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->pdu_retrans_buffer[snP].num_holes, + rlc_pP->tx_data_pdu_buffer[snP].num_holes, snP, so_startP, so_stopP); @@ -312,6 +313,7 @@ void rlc_am_add_hole ( assert(1==2); } - assert(rlc_pP->pdu_retrans_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); - assert(rlc_pP->pdu_retrans_buffer[snP].nack_so_start < rlc_pP->pdu_retrans_buffer[snP].payload_size); + assert(rlc_pP->tx_data_pdu_buffer[snP].num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU); + assert(rlc_pP->tx_data_pdu_buffer[snP].nack_so_start < rlc_pP->tx_data_pdu_buffer[snP].payload_size); } +#endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.h index 902bc5930612c8789df8c6493e06af0306ce7613..68200c0f996fedfab863267f84714534ac078154 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segments_holes.h @@ -32,7 +32,7 @@ * @ingroup _rlc_am_internal_segment_impl_ * @{ */ - +#if 0 #ifndef __RLC_AM_SEGMENT_HOLES_H__ # define __RLC_AM_SEGMENT_HOLES_H__ //----------------------------------------------------------------------------- @@ -108,3 +108,4 @@ protected_rlc_am_segments_holes(void rlc_am_add_hole ( sdu_size_t so_stopP);) /** @} */ #endif +#endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c index d687bf8606f31ad4ec3b3c8bad31886e49286f53..c07e9cd6f3fbd65f51ec07a584784bb6b799ad3d 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c @@ -268,6 +268,14 @@ rlc_am_receive_process_control_pdu( { rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)*first_byte_ppP; sdu_size_t initial_pdu_size = *tb_size_in_bytes_pP; + rlc_sn_t ack_sn = RLC_AM_NEXT_SN(rlc_pP->vt_a); + rlc_sn_t sn_cursor = rlc_pP->vt_a; + rlc_sn_t vt_a_new = rlc_pP->vt_a; + rlc_sn_t sn_data_cnf; + rlc_sn_t nack_sn,prev_nack_sn; + sdu_size_t data_cnf_so_stop = 0x7FFF; + unsigned int nack_index; + boolean_t status = TRUE; if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, tb_size_in_bytes_pP, &rlc_pP->control_pdu_info) >= 0) { @@ -280,11 +288,7 @@ rlc_am_receive_process_control_pdu( rlc_pP->control_pdu_info.ack_sn); rlc_am_display_control_pdu_infos(&rlc_pP->control_pdu_info); - rlc_sn_t ack_sn = rlc_pP->control_pdu_info.ack_sn; - rlc_sn_t sn_cursor = rlc_pP->vt_a; - rlc_sn_t nack_sn; - unsigned int nack_index; - + ack_sn = rlc_pP->control_pdu_info.ack_sn; // 5.2.1 Retransmission // // The transmitting side of an AM RLC entity can receive a negative acknowledgement (notification of reception failure @@ -308,64 +312,127 @@ rlc_am_receive_process_control_pdu( assert(ack_sn < RLC_AM_SN_MODULO); assert(rlc_pP->control_pdu_info.num_nack < RLC_AM_MAX_NACK_IN_STATUS_PDU); - if (rlc_am_in_tx_window(ctxt_pP, rlc_pP, ack_sn) > 0) { - rlc_pP->num_nack_so = 0; - rlc_pP->num_nack_sn = 0; - + /* Note : ackSn can be equal to current vtA only in case the status pdu contains a list of nack_sn with same value = vtA with SOStart/SOEnd */ + /* and meaning the report is not complete due to not enough ressources to fill all SOStart/SOEnd of this NACK_SN */ + if (RLC_AM_DIFF_SN(rlc_pP->vt_s,rlc_pP->vt_a) >= RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a)) + { if (rlc_pP->control_pdu_info.num_nack == 0) { while (sn_cursor != ack_sn) { - if (sn_cursor == rlc_pP->poll_sn) { - rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP); - } - rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor); - sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK; + sn_cursor = RLC_AM_NEXT_SN(sn_cursor); } + + vt_a_new = ack_sn; + sn_data_cnf = RLC_AM_PREV_SN(vt_a_new); } else { nack_index = 0; nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn; + prev_nack_sn = 0x3FFF; - while (sn_cursor != ack_sn) { - if (sn_cursor == rlc_pP->poll_sn) { - rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP); - } + while (sn_cursor != nack_sn) { + rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor); + sn_cursor = RLC_AM_NEXT_SN(sn_cursor); + } + + vt_a_new = nack_sn; + + // catch DataCfn + rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[nack_sn % RLC_AM_WINDOW_SIZE]; + if (tx_data_pdu_buffer_p->retx_payload_size == tx_data_pdu_buffer_p->payload_size) { + sn_data_cnf = RLC_AM_PREV_SN(nack_sn); + } + else if (tx_data_pdu_buffer_p->nack_so_start != 0) { + sn_data_cnf = nack_sn; + data_cnf_so_stop = tx_data_pdu_buffer_p->nack_so_start - 1; + } + else { + sn_data_cnf = RLC_AM_PREV_SN(nack_sn); + } + + while ((sn_cursor != ack_sn) && (status)) { if (sn_cursor != nack_sn) { rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor); } else { - rlc_am_nack_pdu (ctxt_pP, + status = rlc_am_nack_pdu (ctxt_pP, rlc_pP, - sn_cursor, + nack_sn, + prev_nack_sn, rlc_pP->control_pdu_info.nack_list[nack_index].so_start, rlc_pP->control_pdu_info.nack_list[nack_index].so_end); nack_index = nack_index + 1; + prev_nack_sn = nack_sn; - if (nack_index == rlc_pP->control_pdu_info.num_nack) { - nack_sn = 0xFFFF; // value never reached by sn - } else { - nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn; + if (nack_index < rlc_pP->control_pdu_info.num_nack) { + nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn; + } + else if (nack_sn != ack_sn) { + /* general case*/ + nack_sn = ack_sn; + } + else { + /*specific case when the sender did not have enough TBS to fill all SOStart SOEnd for this NACK_SN */ + break; } } - - if ((nack_index < rlc_pP->control_pdu_info.num_nack) && (nack_index > 0)) { - if (rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn != rlc_pP->control_pdu_info.nack_list[nack_index-1].nack_sn) { + if (prev_nack_sn != nack_sn) { + /* do not increment sn_cursor in case of several informations for the same nack_sn */ sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK; - } - } else { - sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK; } } } + + } else { - LOG_N(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN OUT OF WINDOW\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); + LOG_N(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN %d OUT OF WINDOW vtA=%d vtS=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,rlc_pP->vt_a,rlc_pP->vt_s); + status = FALSE; } } else { LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR IN DECODING CONTROL PDU\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); + status = FALSE; + } + + if (status) { + /* Check for Stopping TpollReTx */ + if ((rlc_pP->poll_sn != RLC_SN_UNDEFINED) && + (RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a) > RLC_AM_DIFF_SN(rlc_pP->poll_sn,rlc_pP->vt_a))) { + rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP); + rlc_pP->poll_sn = RLC_SN_UNDEFINED; + } + + //TODO : this part does not cover all cases of Data Cnf and move it at the end of Status PDU processing + sn_cursor = rlc_pP->vt_a; + + // Fix Issue 238 : check sn_data_cnf has been transmitted + if ((rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].flags.transmitted) && + (rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].sn == sn_data_cnf)) { + /* Handle all acked PDU up to and excluding sn_data_cnf */ + while (sn_cursor != sn_data_cnf) { + rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_cursor); + sn_cursor = RLC_AM_NEXT_SN(sn_cursor); + } + + // Handle last SN. TO DO : case of PDU partially ACKED with SDU to be data conf + if (data_cnf_so_stop == 0x7FFF) { + rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_data_cnf); + } + + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU ACK_SN=%d NewvtA=%d OldvtA=%d SnDataCnf=%d DataCnfSOStop=%d vtS=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,sn_data_cnf,data_cnf_so_stop,rlc_pP->vt_s); + } + else { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU WITH NO SDU CNF ACK_SN=%d NewvtA=%d OldvtA=%d vtS=%d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,rlc_pP->vt_s); + } + + /* Update vtA and vtMS */ + rlc_pP->vt_a = vt_a_new; + rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK; } *first_byte_ppP = (uint8_t*)((uint64_t)*first_byte_ppP + initial_pdu_size - *tb_size_in_bytes_pP); @@ -449,6 +516,357 @@ rlc_am_send_status_pdu( // - set the ACK_SN to the SN of the next not received RLC Data PDU which is not indicated as missing in the // resulting STATUS PDU. + signed int nb_bits_to_transmit = rlc_pP->nb_bytes_requested_by_mac << 3; + // minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1 + signed int nb_bits_transmitted = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS; + rlc_am_control_pdu_info_t control_pdu_info; + rlc_am_pdu_info_t *pdu_info_cursor_p = NULL; + rlc_sn_t sn_cursor = 0; + rlc_sn_t sn_nack = rlc_pP->vr_r; + mem_block_t *cursor_p = rlc_pP->receiver_buffer.head; + int all_segments_received = 0; + int waited_so = 0; + mem_block_t *tb_p = NULL; + sdu_size_t pdu_size = 0; + boolean_t status_report_completed = false; + boolean_t segment_loop_end = false; + + memset(&control_pdu_info, 0, sizeof(rlc_am_control_pdu_info_t)); + +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] nb_bits_to_transmit %d (15 already allocated for header)\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + nb_bits_to_transmit); + rlc_am_rx_list_display(rlc_pP, " DISPLAY BEFORE CONSTRUCTION OF STATUS REPORT"); +#endif + + /* Handle no NACK first */ + if (rlc_pP->vr_r == rlc_pP->vr_ms) { + + control_pdu_info.ack_sn = rlc_pP->vr_ms; + status_report_completed = true; +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d ALL ACK WITH ACK_SN %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + rlc_pP->vr_ms); +#endif + } + else if ((cursor_p != NULL) && ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1)) <= nb_bits_to_transmit)) { + + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + sn_cursor = pdu_info_cursor_p->sn; + + /* Set E1 bit for the presence of first NACK_SN/E1/E2 */ + control_pdu_info.e1 = 1; + + // 12 bits = size of NACK_SN field + E1, E2 bits + // 42 bits = size of NACK_SN field + SO_START, SO_END fields, E1, E2 bits + while ((!status_report_completed) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)) + && (cursor_p != NULL) && (nb_bits_transmitted <= nb_bits_to_transmit)) { + + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + sn_cursor = pdu_info_cursor_p->sn; + all_segments_received = ((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received; + + /* First fill NACK_SN with each missing PDU between current sn_nack and sn_cursor */ + while ((sn_nack != sn_cursor) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))) { + if (nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) <= nb_bits_to_transmit) { + /* Fill NACK_SN infos */ + control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_nack; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES; + control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 0; + /* Set E1 for next NACK_SN. The last one will be cleared */ + control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1; + control_pdu_info.num_nack += 1; + nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1)); +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + sn_nack); +#endif + sn_nack = RLC_AM_NEXT_SN(sn_nack); + } + else { + /* Not enough UL TBS*/ + /* latest value of sn_nack shall be used as ACK_SN */ + control_pdu_info.ack_sn = sn_nack; + status_report_completed = true; +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d NOT ENOUGH TBS STOP WITH ACK_SN %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + sn_nack); +#endif + break; + } + } + + if (sn_nack == rlc_pP->vr_ms) { + break; + } + + /* Now process all Segments of sn_cursor if PDU not fully received */ + if ((!status_report_completed) && (all_segments_received == 0) && (sn_cursor != rlc_pP->vr_ms)) { + AssertFatal (sn_nack == sn_cursor, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id); + + /* First ensure there is enough TBS for at least 1 SOStart/SOEnd, else break */ + if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) { + /* Init loop flags */ + /* Check lsf */ + segment_loop_end = (pdu_info_cursor_p->lsf == 1); + + /* Init first SO Start according to first segment */ + if (pdu_info_cursor_p->so) { + /* Fill the first SO */ + control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1; + control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1; + /* Set E1 for next NACK_SN. The last one will be cleared */ + control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1; + control_pdu_info.num_nack += 1; + nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)); +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + sn_cursor, + 0, + pdu_info_cursor_p->so - 1); +#endif + waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size; + } + else { + waited_so = pdu_info_cursor_p->payload_size; + } + + /* Go to next segment */ + cursor_p = cursor_p->next; + if (cursor_p != NULL) + { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + + /* Find the first discontinuity and then fill SOStart/SOEnd */ + while (!segment_loop_end) { + if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)) { + + /* PDU segment is for the same SN*/ + /* Check lsf */ + segment_loop_end = (pdu_info_cursor_p->lsf == 1); + + if (waited_so < pdu_info_cursor_p->so) { + /* SO is greater than previous received portion : gap identified to fill */ + if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) { + control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1; + control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1; + /* Set E1 for next NACK_SN. The last one will be cleared */ + control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1; + control_pdu_info.num_nack += 1; + nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)); +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + sn_cursor, + waited_so, + pdu_info_cursor_p->so); +#endif + } + else { + /* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */ + control_pdu_info.ack_sn = sn_cursor; + status_report_completed = true; + segment_loop_end = true; + break; + } + } + else { + /* contiguous segment: only update waited_so */ + /* Assuming so and payload_size updated according to duplication removal done at reception ... */ + waited_so += pdu_info_cursor_p->payload_size; + } + + /* Go to next received PDU or PDU Segment */ + cursor_p = cursor_p->next; + if (cursor_p != NULL) + { + pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; + } + + } //end if (cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor) + else { + /* Previous PDU segment was the last one and did not have lsf indication : fill the latest gap */ + if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) { + control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so; + control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES; + control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1; + /* Set E1 for next NACK_SN. The last one will be cleared */ + control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1; + control_pdu_info.num_nack += 1; + nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)); +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING LAST NACK %04d SO START %05d SO END %05d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + sn_cursor, + waited_so, + RLC_AM_STATUS_PDU_SO_END_ALL_BYTES); +#endif + } + else { + /* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */ + control_pdu_info.ack_sn = sn_cursor; + status_report_completed = true; + } + + segment_loop_end = true; + } + } //end while (!segment_loop_end) + } // end if enough resource for transmitting at least one SOStart/SOEnd + else { + /* Not enough UL TBS to set at least one SOStart/SOEnd */ + /* latest value of sn_nack shall be used as ACK_SN */ + control_pdu_info.ack_sn = sn_nack; + status_report_completed = true; + } + } // end while on all PDU segments of sn_cursor + else { + /* Go to next received PDU or PDU segment with different SN */ + do { + cursor_p = cursor_p->next; + } while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.sn == sn_cursor)); + } + + /* Increment sn_nack except if sn_cursor = vrMS and if current SN was not fully received */ + if (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)) { + sn_nack = RLC_AM_NEXT_SN(sn_cursor); + } + else { + sn_nack = rlc_pP->vr_ms; + } + + + } // End main while NACK_SN + + /* Clear E1 of last nack_sn entry */ + AssertFatal ((control_pdu_info.num_nack) || (all_segments_received == 0), "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n", + rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id); + if (control_pdu_info.num_nack) { + control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 0; + } + + + /* Set ACK_SN unless it was set before */ + if (!status_report_completed){ + + control_pdu_info.ack_sn = sn_nack; + } + + } else { + /* reception buffer empty or not enough TBS for filling at least 1 NACK_SN + E1 + E2 */ + control_pdu_info.ack_sn = rlc_pP->vr_r; +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d = VR(R)\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + control_pdu_info.ack_sn); +#endif + } + + + //msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] nb_bits_to_transmit %d\n", + // rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame,nb_bits_to_transmit); + +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d NUM NACK %d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + control_pdu_info.ack_sn, + control_pdu_info.num_nack); +#endif + + + /* encode the control pdu */ + pdu_size = (nb_bits_transmitted + 7) >> 3; + AssertFatal (pdu_size <= rlc_pP->nb_bytes_requested_by_mac, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n", + pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id); + + +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d forecast pdu_size %d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + __LINE__, + pdu_size); +#endif + tb_p = get_free_mem_block(sizeof(struct mac_tb_req) + pdu_size, __func__); + memset(tb_p->data, 0, sizeof(struct mac_tb_req) + pdu_size); + //estimation only ((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size; + ((struct mac_tb_req*)(tb_p->data))->data_ptr = (uint8_t*)&(tb_p->data[sizeof(struct mac_tb_req)]); + + // warning reuse of pdu_size + // TODO : rlc_am_write_status_pdu should be rewritten as not very tested ... + pdu_size = rlc_am_write_status_pdu(ctxt_pP, rlc_pP,(rlc_am_pdu_sn_10_t*)(((struct mac_tb_req*)(tb_p->data))->data_ptr), &control_pdu_info); + ((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size; + //assert((((struct mac_tb_req*)(tb_p->data))->tb_size) < 3000); + +#if TRACE_RLC_AM_STATUS_CREATION + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] SEND STATUS PDU SIZE %d, rlc_pP->nb_bytes_requested_by_mac %d, nb_bits_to_transmit>>3 %d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + pdu_size, + rlc_pP->nb_bytes_requested_by_mac, + nb_bits_to_transmit >> 3); +#endif + + AssertFatal (pdu_size == ((nb_bits_transmitted + 7) >> 3), "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n", + pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id); + + // remaining bytes to transmit for RLC (retrans pdus and new data pdus) + rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - pdu_size; + // put pdu in trans + list_add_head(tb_p, &rlc_pP->control_pdu_list); + rlc_pP->stat_tx_control_pdu += 1; + rlc_pP->stat_tx_control_bytes += pdu_size; + +} + + +#if 0 +//----------------------------------------------------------------------------- +void +rlc_am_send_status_pdu_backup( + const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlc_pP +) +{ + // When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall: + // - if t-StatusProhibit is not running: + // - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer; + // - else: + // - at the first transmission opportunity indicated by lower layer after t-StatusProhibit expires, construct a single + // STATUS PDU even if status reporting was triggered several times while t-StatusProhibit was running and + // deliver it to lower layer; + // + // When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall: + // - start t-StatusProhibit. + // + // When constructing a STATUS PDU, the AM RLC entity shall: + // - for the AMD PDUs with SN such that VR(R) <= SN < VR(MR) that has not been completely received yet, in + // increasing SN of PDUs and increasing byte segment order within PDUs, starting with SN = VR(R) up to + // the point where the resulting STATUS PDU still fits to the total size of RLC PDU(s) indicated by lower layer: + // - for an AMD PDU for which no byte segments have been received yet:: + // - include in the STATUS PDU a NACK_SN which is set to the SN of the AMD PDU; + // - for a continuous sequence of byte segments of a partly received AMD PDU that have not been received yet: + // - include in the STATUS PDU a set of NACK_SN, SOstart and SOend + // - set the ACK_SN to the SN of the next not received RLC Data PDU which is not indicated as missing in the + // resulting STATUS PDU. + signed int nb_bits_to_transmit = rlc_pP->nb_bytes_requested_by_mac << 3; rlc_am_control_pdu_info_t control_pdu_info; rlc_am_pdu_info_t *pdu_info_cursor_p = NULL; @@ -470,11 +888,12 @@ rlc_am_send_status_pdu( rlc_am_rx_list_display(rlc_pP, " DISPLAY BEFORE CONSTRUCTION OF STATUS REPORT"); #endif + if (cursor_p != NULL) { pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info; sn_cursor = pdu_info_cursor_p->sn; - while (rlc_am_in_rx_window(ctxt_pP, rlc_pP, sn_cursor) == 0) { + while (!(RLC_AM_SN_IN_WINDOW(sn_cursor, rlc_pP->vr_r))) { cursor_p = cursor_p->next; previous_sn_cursor = sn_cursor; @@ -757,3 +1176,5 @@ end_push_nack: rlc_pP->stat_tx_control_bytes += pdu_size; } +#endif + diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_structs.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_structs.h index 02112fe736783ba6c997d3f1292c799698ff65b6..2b75cb21a7a8eaf63a9d42a9239e654bb366cb37 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_structs.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_structs.h @@ -88,9 +88,12 @@ typedef struct rlc_am_tx_sdu_management { * \brief Structure containing PDU variables related to its retransmission. */ typedef struct pdu_management_flags { + uint8_t transmitted:1; /*!< \brief Boolean telling that this PDU is not empty and has been at least transmitted once. */ uint8_t ack:1; /*!< \brief Boolean telling that this PDU has been acknowledged. */ + uint8_t nack:1; /*!< \brief Boolean telling that this PDU has been acknowledged negatively. */ uint8_t retransmit:1; /*!< \brief Boolean telling a retransmission is scheduled for this PDU. */ - uint8_t dummy:6; /*!< \brief Free bits. */ + uint8_t max_retransmit:1; /*!< \brief Boolean telling max retransmission has been hit for this PDU. */ + uint8_t dummy:3; /*!< \brief Free bits. */ } pdu_management_flags_t; @@ -107,15 +110,17 @@ typedef struct rlc_am_tx_data_pdu_management { sdu_size_t hole_so_start [RLC_AM_MAX_HOLES_REPORT_PER_PDU]; /*!< \brief Array containing the start segment offsets for marking a hole (negative acknowledged area) in the PDU. */ sdu_size_t hole_so_stop [RLC_AM_MAX_HOLES_REPORT_PER_PDU]; /*!< \brief Array containing the stop segment offsets for marking a hole (negative acknowledged area) in the PDU. */ uint8_t num_holes; /*!< \brief Number of registereg holes in hole_so_start[], hole_so_stop[]. */ + uint8_t retx_hole_index; /*!< \brief Next index of registered holes to retransmit. */ sdu_size_t header_and_payload_size; /*!< \brief Size of the PDU in bytes, including header and payload. */ sdu_size_t payload_size; /*!< \brief Size of the PDU payload in bytes. */ + sdu_size_t retx_payload_size; /*!< \brief Size of the PDU payload to be retransmitted in bytes including all Segment portions. */ rlc_sn_t sn; /*!< \brief Sequence number of the PDU. */ sdu_size_t nack_so_start; /*!< \brief Lowest NACK start segment offset, must be set to 0 if global NACK. */ - sdu_size_t nack_so_stop; /*!< \brief Highest NACK stop segment offset, must be set to data_size if global NACK */ + sdu_size_t nack_so_stop; /*!< \brief Highest NACK stop segment offset, must be set to data_size - 1 if global NACK */ int8_t nb_sdus; /*!< \brief Number of sdu having segments in this pdu. */ - int8_t - retx_count; /*!< \brief Counts the number of retransmissions of an AMD PDU (see subclause 5.2.1). There is one RETX_COUNT counter per PDU that needs to be retransmitted. there is one VT(DAT) for each PDU and it is incremented each time the PDU is transmitted. */ + int8_t retx_count; /*!< \brief Counts the number of already occurred retransmissions of an AMD PDU (see subclause 5.2.1). */ + int8_t retx_count_next; /*!< \brief Counts the number of already occurred retransmissions plus the latest pending one. */ pdu_management_flags_t flags; /*!< \brief PDU variables related to its retransmission. */ } rlc_am_tx_data_pdu_management_t; @@ -228,14 +233,48 @@ typedef struct rlc_am_timer { * @{ */ +typedef enum rlc_am_rx_segment_reassemble_info +{ + /** No Reassembly scheduled */ + RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO = 0, + /** Reassembly scheduled */ + RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING = 1, + /** Reassembly done */ + RLC_AM_RX_PDU_SEGMENT_REASSEMBLED = 2 + +} rlc_am_rx_segment_reassemble_info_t; + /*! \struct rlc_am_rx_pdu_management_t * \brief Structure for storing decoded informations from the header of a AMD PDU or AMD PDU segment and information on reassembly. */ typedef struct rlc_am_rx_pdu_management { rlc_am_pdu_info_t pdu_info; /*!< \brief Field for storing decoded informations from the header of a AMD PDU or AMD PDU segment. */ uint8_t all_segments_received; /*!< \brief Is all segments of PDU SN have been received. */ + rlc_am_rx_segment_reassemble_info_t segment_reassembled; /*!< \brief if the segment for SN=vrR is reassembled but not discarded yet. */ } rlc_am_rx_pdu_management_t; /** @} */ + +typedef enum rlc_am_rx_pdu_status +{ + /** PDU okay. */ + RLC_AM_DATA_PDU_STATUS_OK = 0, + /** SN outside RX window */ + RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW = 1, + /** SN already available */ + RLC_AM_DATA_PDU_STATUS_SN_DUPLICATE = 2, + /** SN already available */ + RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE = 3, + /** Buffer full */ + RLC_AM_DATA_PDU_STATUS_BUFFER_FULL = 4, + /** Header Error (LI,SO...) */ + RLC_AM_DATA_PDU_STATUS_HEADER_ERROR = 5, + /** Unknown bearer */ + RLC_AM_DATA_PDU_STATUS_INVALID_BEARER = 6, + /** RLC in wrong state */ + RLC_AM_DATA_PDU_STATUS_WRONG_STATE = 7 + +} rlc_am_rx_pdu_status_t; + /*! \cond PRIVATE */ //----------------------------------------------------------------------------- // interlayers optimizations diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c index 8e201a949b84796288ee65a9b5797d4528495131..86cafb89ce441ab8cad42825bc661a8ac131cc11 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c @@ -228,7 +228,7 @@ void rlc_am_v9_3_0_test_read_write_bit_field() uint8_t* byte_pos_read = g_buffer; uint16_t read_value; - memset (g_buffer, 0, 1024); + memset (g_buffer, 0, sizeof(g_buffer)); // byte 0 rlc_am_write8_bit_field(&byte_pos_write, &bit_pos_write, 1, 1); rlc_am_write8_bit_field(&byte_pos_write, &bit_pos_write, 1, 0); diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c index aa3fdb909a90313e6c76e94f38f3601eda79a5f7..2dfa472523f5a536f7515ccaaa8d1fbbc218168b 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c @@ -77,10 +77,41 @@ rlc_am_check_timer_poll_retransmit( LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); + /* Check for any retransmittable PDU if Buffer Occupancy empty or window stall */ + if (((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) || + (rlc_pP->vt_s == rlc_pP->vt_ms)) { + // force BO to be > 0 + rlc_sn_t sn = RLC_AM_PREV_SN(rlc_pP->vt_s); + rlc_sn_t sn_end = RLC_AM_PREV_SN(rlc_pP->vt_a); + rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p; + + /* Look for the first retransmittable PDU starting from vtS - 1 */ + while (sn != sn_end) { + tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE]; + AssertFatal (tx_data_pdu_buffer_p->mem_block != NULL, "RLC AM Tpoll Retx expiry sn=%d is empty vtA=%d vtS=%d LcId=%d\n", + sn, rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id); + if ((tx_data_pdu_buffer_p->flags.ack == 0) && (tx_data_pdu_buffer_p->flags.max_retransmit == 0)) { + tx_data_pdu_buffer_p->flags.retransmit = 1; + tx_data_pdu_buffer_p->retx_payload_size = tx_data_pdu_buffer_p->payload_size; + if (tx_data_pdu_buffer_p->retx_count == tx_data_pdu_buffer_p->retx_count_next) { + tx_data_pdu_buffer_p->retx_count_next ++; + } + rlc_pP->retrans_num_pdus += 1; + rlc_pP->retrans_num_bytes_to_retransmit += tx_data_pdu_buffer_p->payload_size; + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT PUT SN=%d in ReTx Buffer\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),tx_data_pdu_buffer_p->sn); + break; + } + else + { + sn = RLC_AM_PREV_SN(sn); + } + } + } + rlc_pP->force_poll= TRUE; - //#warning TO DO rlc_am_check_timer_poll_retransmit - rlc_pP->t_poll_retransmit.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_poll_retransmit.ms_duration; + //BugFix : new ms_time_out is computed when next poll is transmitter } } } @@ -119,9 +150,9 @@ rlc_am_start_timer_poll_retransmit( rlc_am_entity_t * const rlc_pP ) { - rlc_pP->t_poll_retransmit.timed_out = 0; + /* Stop timer if it was previously running */ + rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP,rlc_pP); - if (rlc_pP->t_poll_retransmit.running == 0) { if (rlc_pP->t_poll_retransmit.ms_duration > 0) { rlc_pP->t_poll_retransmit.running = 1; rlc_pP->t_poll_retransmit.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_poll_retransmit.ms_duration; @@ -138,14 +169,7 @@ rlc_am_start_timer_poll_retransmit( LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] NOT STARTED, CAUSE CONFIGURED 0 ms\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); } - } else { -#if MESSAGE_CHART_GENERATOR_RLC_MAC - MSC_LOG_EVENT((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,\ - "0 "PROTOCOL_RLC_AM_MSC_FMT" t_poll_retransmit not restarted (TO %u ms)",\ - PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP,rlc_pP), rlc_pP->t_poll_retransmit.ms_time_out); -#endif - } } //----------------------------------------------------------------------------- void diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_reordering.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_reordering.c index 3bbc2e87ac1aa70de07d2f0892eb84ffb34116a3..cec0dffd1d726ea6027e809b630cff5504ae4c46 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_reordering.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_reordering.c @@ -70,6 +70,8 @@ rlc_am_check_timer_reordering( PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP,rlc_pP)); #endif + AssertFatal (rlc_pP->vr_x != RLC_SN_UNDEFINED, "RLC AM TReordering Expiry vrX not defined LcId=%d\n", rlc_pP->channel_id); + rlc_pP->t_reordering.running = 0; rlc_pP->t_reordering.timed_out = 1; rlc_pP->stat_timer_reordering_timed_out += 1; @@ -77,38 +79,56 @@ rlc_am_check_timer_reordering( rlc_am_pdu_info_t* pdu_info; mem_block_t* cursor; cursor = rlc_pP->receiver_buffer.head; + rlc_usn_t vr_ms_new = rlc_pP->vr_x; - if (cursor) { - do { - pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info; + AssertFatal (cursor != NULL, "RLC AM TReordering Expiry Rx PDU list empty LcId=%d\n", rlc_pP->channel_id); - // NOT VERY SURE ABOUT THAT, THINK ABOUT IT - rlc_pP->vr_ms = (pdu_info->sn + 1) & RLC_AM_SN_MASK; + /* go to memblock up to vrX*/ + pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info; + while ((cursor != NULL) && (RLC_AM_DIFF_SN(pdu_info->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(vr_ms_new,rlc_pP->vr_r))) { + cursor = cursor->next; + if (cursor != NULL) { + pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info; + } + } - if (rlc_am_sn_gte_vr_x(ctxt_pP, rlc_pP, pdu_info->sn)) { - if (((rlc_am_rx_pdu_management_t*)(cursor->data))->all_segments_received == 0) { - rlc_pP->vr_ms = pdu_info->sn; - break; - } - } + /* Now find a SN for which either no PDU is received or partially received */ + while ((cursor != NULL) && (vr_ms_new != rlc_pP->vr_h) && (pdu_info->sn == vr_ms_new) && (((rlc_am_rx_pdu_management_t*)(cursor->data))->all_segments_received > 0)) { + /* Increment vrMS if the PDU is fully received or if this is the last PDU segment */ + if ((pdu_info->rf == 0) || (pdu_info->lsf == 1)) { + vr_ms_new = RLC_AM_NEXT_SN(vr_ms_new); + } + cursor = cursor->next; + if (cursor != NULL) { + pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info; + } + } - cursor = cursor->next; - } while (cursor != NULL); + /* Update vr_ms */ + rlc_pP->vr_ms = vr_ms_new; - LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT UPDATED VR(MS) %04d\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), - rlc_pP->vr_ms); - } - if (rlc_am_sn_gt_vr_ms(ctxt_pP, rlc_pP, rlc_pP->vr_h)) { + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT UPDATED VR(MS) %04d\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), + rlc_pP->vr_ms); + + /* if new vrMS is lower than vrH, update vrX and restart timerReordering */ + if (rlc_pP->vr_ms != rlc_pP->vr_h) { rlc_pP->vr_x = rlc_pP->vr_h; rlc_pP->t_reordering.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_reordering.ms_duration; + + LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT, RESTARTED T-REORDERING, UPDATED VR(X) to VR(R) %04d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->vr_x); } - rlc_pP->status_requested = 1; + /* Trigger a STATUS report */ + RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING); + // Clear Delay flag if it was setup as it is useless due to Status PDU to be sent for TReordering expiry + RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED); + rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; + } } } diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_status_prohibit.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_status_prohibit.c index b41fa1c17fd9bda1e1e5bf493d5f974f9fd6fe94..65ea0561205b6d09d28026edac333978e9a0b364 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_status_prohibit.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_status_prohibit.c @@ -70,6 +70,8 @@ rlc_am_check_timer_status_prohibit( PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); //#warning TO DO rlc_am_check_timer_status_prohibit rlc_am_stop_and_reset_timer_status_prohibit(ctxt_pP, rlc_pP); + /* Clear StatusProhibit flag */ + RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_PROHIBIT); //rlc_pP->t_status_prohibit.frame_time_out = ctxt_pP->frame + rlc_pP->t_status_prohibit.time_out; } } @@ -110,6 +112,7 @@ rlc_am_start_timer_status_prohibit( rlc_pP->t_status_prohibit.running = 1; rlc_pP->t_status_prohibit.ms_time_out = rlc_pP->t_status_prohibit.ms_duration + PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP); rlc_pP->t_status_prohibit.ms_start = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP); + RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_PROHIBIT); LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-STATUS-PROHIBIT] STARTED (TIME-OUT = %u ms)\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->t_status_prohibit.ms_time_out); diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c index 51440d0bfa33bbd6688374173bb5e2d9ad630f28..e3322d9410b62829e2a4bede9937d70adb0b8b2b 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c @@ -434,7 +434,6 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP int32_t diff_time=0; rlc_um_entity_t *rlc_p = NULL; mem_block_t *mb_p = NULL; - unsigned int max_li_overhead = 0; status_resp.buffer_occupancy_in_pdus = 0; status_resp.buffer_occupancy_in_bytes = 0; @@ -454,20 +453,11 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) { - //Fix on full Header size - if (enb_flagP == ENB_FLAG_NO) - { - // compute Length Indicator overhead to inform MAC of maximum full RLC PDU size according to stored SDUs - // For UE scheduler - // Could be useful for eNB: to be checked - if (rlc_p->input_sdus.nb_elements <= 1) { - max_li_overhead = 0; - } else { - unsigned int num_li = rlc_p->input_sdus.nb_elements - 1; - max_li_overhead = num_li + (num_li >> 1) + (num_li & 1); - } - } - status_resp.buffer_occupancy_in_bytes += (rlc_p->tx_header_min_length_in_bytes + max_li_overhead); + if (enb_flagP == ENB_FLAG_YES) { + /* For eNB: add minimum RLC UM header size for the scheduler */ + /* For UE : RLC header part is not taken into account for BSR reporting (cf 36.321) */ + status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes; + } status_resp.buffer_occupancy_in_pdus = rlc_p->input_sdus.nb_elements; diff_time = ctxt_pP->frame - ((struct rlc_um_tx_sdu_management *)mb_p->data)->sdu_creation_time; @@ -520,9 +510,19 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP return status_resp; } +//----------------------------------------------------------------------------- +void +rlc_um_set_nb_bytes_requested_by_mac ( + void * rlc_pP, + const tb_size_t tb_sizeP +) +{ + ((rlc_um_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP; +} + //----------------------------------------------------------------------------- struct mac_data_req -rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP) +rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP,const eNB_flag_t enb_flagP) { struct mac_data_req data_req; int16_t tb_size_in_bytes; @@ -544,10 +544,13 @@ rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP) list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data); - data_req.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (l_rlc_p); + if (enb_flagP) { + // redundant in UE MAC Tx processing and not used in eNB scheduler ... + data_req.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (l_rlc_p); - if (data_req.buffer_occupancy_in_bytes > 0) { - data_req.buffer_occupancy_in_bytes += l_rlc_p->tx_header_min_length_in_bytes; + if (data_req.buffer_occupancy_in_bytes > 0) { + data_req.buffer_occupancy_in_bytes += l_rlc_p->tx_header_min_length_in_bytes; + } } data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state; diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h index 5951eaf1490c58f9b62cc4fca0aabeb4875ce163..87cf2e2f3764b8d17c60b917070aa013c4ccba75 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h @@ -188,13 +188,21 @@ protected_rlc_um( void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_ */ public_rlc_um( struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP);) -/*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP) +/*! \fn void rlc_um_set_nb_bytes_requested_by_mac (rlc_um_entity_t * const rlc_pP, const tb_size_t tb_sizeP) +* \brief Set available TBS size for MAC Tx. +* \param[in] rlc_pP RLC UM protocol instance pointer. +* \param[in] tb_sizeP remaining TBS in bytes. +*/ +public_rlc_um( void rlc_um_set_nb_bytes_requested_by_mac (rlc_um_entity_t * const rlc_pP, const tb_size_t tb_sizeP);) + +/*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,const eNB_flag_t enb_flagP) * \brief Gives PDUs to lower layer MAC. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC UM protocol instance pointer. +* \param[in] enb_flagP eNB or UE flag. * \return A PDU of the previously requested number of bytes, and the updated maximum number of bytes that can be served by RLC instance to MAC for next RLC transmission. */ -public_rlc_um( struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP);) +public_rlc_um( struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,const eNB_flag_t enb_flagP);) /*! \fn void rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,struct mac_data_ind data_indP) @@ -205,6 +213,11 @@ public_rlc_um( struct mac_data_req rlc_um_mac_data_request (const protocol_ct */ public_rlc_um( void rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, struct mac_data_ind data_indP);) +/*! \fn uint32_t rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP) +* \brief Gets Tx Buffer Occupancy. +* \param[in] rlc_pP RLC UM protocol instance pointer.) +*/ +public_rlc_um( uint32_t rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP);) /*! \fn void rlc_um_data_req (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, mem_block_t *sduP) * \brief Interface with higher layers, buffer higher layer SDUS for transmission. diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_constants.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_constants.h index 2d0a875edb51ee6c585ce9906d3879abc47f9726..34d97de59d35b96cb7ebfb0403d23d5e8269a813 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_constants.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_constants.h @@ -53,7 +53,7 @@ // UM_Window_Size = 512 when a 10 bit SN is configured and UM_Window_Size = 0 // when the receiving UM RLC entity is configured for MCCH or MTCH. // li field (values shifted 1 bit left) -# define RLC_UM_SEGMENT_NB_MAX_LI_PER_PDU 24 +# define RLC_UM_SEGMENT_NB_MAX_LI_PER_PDU 128 //---------------------------------------------------------- // Events defined for state model of the acknowledged mode entity /** Internal event defined for state model of the RLC UM. */ diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c index bda2b884581d885c96fcdccfa7ea45b1df3756a8..14ca1a62a985674078cd7b7542ab5b83e5a0a48c 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c @@ -78,7 +78,11 @@ void config_req_rlc_um ( } } //----------------------------------------------------------------------------- +#if defined(Rel14) +const uint32_t const t_Reordering_tab[32] = {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200,1600}; +#else const uint32_t const t_Reordering_tab[T_Reordering_spare1] = {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200}; +#endif void config_req_rlc_um_asn1 ( const protocol_ctxt_t* const ctxt_pP, @@ -99,7 +103,7 @@ void config_req_rlc_um_asn1 ( hash_key_t key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP); hashtable_rc_t h_rc; -#if Rel10 +#if defined(Rel10) || defined(Rel14) if (mbms_flagP) { AssertFatal(dl_rlc_pP, "No RLC UM DL config"); @@ -194,7 +198,11 @@ void config_req_rlc_um_asn1 ( return; } +#if defined(Rel14) + if (dl_rlc_pP->t_Reordering<32) { +#else if (dl_rlc_pP->t_Reordering<T_Reordering_spare1) { +#endif t_Reordering = t_Reordering_tab[dl_rlc_pP->t_Reordering]; } else { LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID T_Reordering %ld, RLC NOT CONFIGURED\n", diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_dar.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_dar.c index 4255464e3a220b4c2f5227bf47b63f5fcfd47b0b..c00e87c4e09fa3a29cb599f792c4e9bc82d719d4 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_dar.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_dar.c @@ -183,7 +183,7 @@ int rlc_um_read_length_indicators(unsigned char**data_ppP, rlc_um_e_li_t* e_liP, // AssertFatal(*data_size_pP >= 0, "Invalid data_size!"); } - if (*num_li_pP >= RLC_UM_SEGMENT_NB_MAX_LI_PER_PDU) { + if (*num_li_pP > RLC_UM_SEGMENT_NB_MAX_LI_PER_PDU) { return -1; } } diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c index 96057231a6596f07fc23ed124a902f34f1e534a5..7aca1b9cc63814012a46222ab554893957608ae8 100644 --- a/openair2/LAYER2/RLC/rlc.c +++ b/openair2/LAYER2/RLC/rlc.c @@ -328,7 +328,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP, hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_rc; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) rlc_mbms_id_t *mbms_id_p = NULL; logical_chan_id_t log_ch_id = 0; #endif @@ -342,7 +342,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP, sdu_sizeP, sdu_pP); #endif -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #else AssertFatal(MBMS_flagP == 0, "MBMS_flagP %u", MBMS_flagP); #endif @@ -366,13 +366,13 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP, DevAssert(sdu_pP != NULL); DevCheck(sdu_sizeP > 0, sdu_sizeP, 0, 0); -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) DevCheck(MBMS_flagP == 0, MBMS_flagP, 0, 0); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_IN); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flagP == TRUE) { if (ctxt_pP->enb_flag) { @@ -499,7 +499,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP, } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) } else { /* MBMS_flag != 0 */ // LOG_I(RLC,"DUY rlc_data_req: mbms_rb_id in RLC instant is: %d\n", mbms_rb_id); if (sdu_pP != NULL) { @@ -538,7 +538,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP, else /* MBMS_flag != 0 */ { free_mem_block(sdu_pP, __func__); - LOG_E(RLC, "MBMS_flag != 0 while Rel10 is not defined...\n"); + LOG_E(RLC, "MBMS_flag != 0 while Rel10/Rel14 is not defined...\n"); //handle_event(ERROR,"FILE %s FONCTION rlc_data_req() LINE %s : parameter module_id out of bounds :%d\n", __FILE__, __LINE__, module_idP); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT); return RLC_OP_STATUS_BAD_PARAMETER; @@ -617,7 +617,7 @@ rlc_module_init (void) AssertFatal(rlc_coll_p != NULL, "UNRECOVERABLE error, RLC hashtable_create failed"); for (module_id1=0; module_id1 < NUMBER_OF_UE_MAX; module_id1++) { -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) for (k=0; k < RLC_MAX_MBMS_LC; k++) { rlc_mbms_lcid2service_session_id_ue[module_id1][k].service_id = 0; @@ -632,7 +632,7 @@ rlc_module_init (void) } for (module_id1=0; module_id1 < NUMBER_OF_eNB_MAX; module_id1++) { -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) for (k=0; k < RLC_MAX_MBMS_LC; k++) { rlc_mbms_lcid2service_session_id_eNB[module_id1][k].service_id = 0; diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index 3fd5b8c3bcfef9cb0f016b1e8db3b00a17102950..3d6be205249b0284c2f9062c838a38a88051964c 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -55,7 +55,7 @@ # include "SRB-ToAddModList.h" # include "DRB-ToReleaseList.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "PMCH-InfoList-r9.h" #endif @@ -224,7 +224,7 @@ typedef struct rlc_mbms_id_s { mbms_session_id_t session_id; } rlc_mbms_id_t; -#if !defined(Rel10) +#if !defined(Rel10) && !defined(Rel14) # if !defined(maxServiceCount) //unused arrays rlc_mbms_array_ue rlc_mbms_array_eNB # define maxServiceCount 1 @@ -309,7 +309,7 @@ private_rlc_mac(struct mac_data_ind mac_rlc_deserialize_tb (char*, tb_size_t, //----------------------------------------------------------------------------- // PUBLIC INTERFACE WITH RRC //----------------------------------------------------------------------------- -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /*! \fn rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, const SRB_ToAddMod_t* const srb2addmod, const DRB_ToAddModList_t* const drb2add_listP, const DRB_ToReleaseList_t* const drb2release_listP, const PMCH_InfoList_r9_t * const pmch_info_listP) * \brief Function for RRC to configure a Radio Bearer. * \param[in] ctxtP Running context. @@ -436,10 +436,11 @@ public_rlc_rrc(void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_d * \param [in] eNB_flagP Flag to indicate eNB (1) or UE (0) * \param [in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0) * \param [in] rb_idP Radio bearer identifier. +* \param [in] tb_sizeP Available Tx TBS in bytes. For UE only. * \param [in,out] bufferP Memory area to fill with the bytes requested by MAC. * \return A status about the processing, OK or error code. */ -public_rlc_mac(tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char*);) +public_rlc_mac(tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, const tb_size_t,char*);) /*! \fn void mac_rlc_data_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, uint32_t frameP, char* bufferP, tb_size_t tb_sizeP, num_tb_t num_tbP, crc_t *crcs) * \brief Interface with MAC layer, deserialize the transport blocks sent by MAC, then map data indication to the RLC instance corresponding to the radio bearer identifier. @@ -457,18 +458,31 @@ public_rlc_mac(tbs_size_t mac_rlc_data_req (const module_id_t, co public_rlc_mac(void mac_rlc_data_ind (const module_id_t, const rnti_t, const eNB_index_t,const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char*, tb_size_t, num_tb_t, crc_t* );) -/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, tb_size_t tb_sizeP) +/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, tb_size_t tb_sizeP) * \brief Interface with MAC layer, request and set the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier. * \param[in] mod_idP Virtualized module identifier. * \param[in] rntiP UE identifier. * \param[in] frameP Frame index. +* \param[in] subframeP SubFrame index. * \param[in] eNB_flagP Flag to indicate eNB operation (1 true, 0 false) * \param[in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0) * \param[in] rb_idP Radio bearer identifier. * \param[in] tb_sizeP Size of a transport block set in bytes. * \return The maximum number of bytes that the RLC instance can send in the next transmission sequence. */ -public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t );) +public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t );) + +/*! \fn rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(const module_id_t module_idP, const rnti_t rntiP, const eNB_index_t eNB_index, const frame_t frameP, const sub_frame_t subframeP,const eNB_flag_t enb_flagP, const logical_chan_id_t channel_idP) +* \brief Interface with MAC layer, UE only: request and get the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier. +* \param[in] mod_idP Virtualized module identifier. +* \param[in] rntiP UE identifier. +* \param[in] frameP Frame index. +* \param[in] subframeP SubFrame index. +* \param[in] eNB_flagP Flag to indicate eNB operation (1 true, 0 false) +* \param[in] channel_idP Logical Channel identifier. +* \return The maximum number of bytes that the RLC instance can send in the next transmission sequence. +*/ +public_rlc_mac(rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const logical_chan_id_t );) //----------------------------------------------------------------------------- // RLC methods //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/RLC/rlc_def.h b/openair2/LAYER2/RLC/rlc_def.h index 124ba509b5b2825fa48a2beff0318c7db1268d59..929d66b70bc55f77f4dbe26c02d874d32edcc021 100644 --- a/openair2/LAYER2/RLC/rlc_def.h +++ b/openair2/LAYER2/RLC/rlc_def.h @@ -64,6 +64,7 @@ enum RLC_OPERATION_MODE { TRANSMITTER_ONLY = 0x00, // dimensions # define SN_12BITS_MASK 0x0FFF # define RLC_SN_OVERFLOW 0xFFFF +# define RLC_SN_UNDEFINED RLC_SN_OVERFLOW //---------------------------------------------------------- // DISCARD //---------------------------------------------------------- diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c index d43a90ed6a5d5d982f3a9d26ec094d9597182fd1..b4061ad29f9b9adc1e1adc2d57897541da7a2d8e 100644 --- a/openair2/LAYER2/RLC/rlc_mac.c +++ b/openair2/LAYER2/RLC/rlc_mac.c @@ -125,6 +125,7 @@ tbs_size_t mac_rlc_data_req( const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, char *buffer_pP) { //----------------------------------------------------------------------------- @@ -189,12 +190,14 @@ tbs_size_t mac_rlc_data_req( break; case RLC_MODE_AM: - data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am); + if (!enb_flagP) rlc_am_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.am,tb_sizeP); + data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am,enb_flagP); ret_tb_size =mac_rlc_serialize_tb(buffer_pP, data_request.data); break; case RLC_MODE_UM: - data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um); + if (!enb_flagP) rlc_um_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.um,tb_sizeP); + data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um,enb_flagP); ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data); break; @@ -320,6 +323,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( const rnti_t rntiP, const eNB_index_t eNB_index, const frame_t frameP, + const sub_frame_t subframeP, const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, @@ -337,7 +341,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( srb_flag_t srb_flag = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO; protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, subframeP, eNB_index); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_STATUS_IND,VCD_FUNCTION_IN); memset (&mac_rlc_status_resp, 0, sizeof(mac_rlc_status_resp_t)); @@ -397,7 +401,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_AM: - status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tb_sizeP, tx_status); + status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tb_sizeP, tx_status,enb_flagP); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send; @@ -430,3 +434,65 @@ mac_rlc_status_resp_t mac_rlc_status_ind( return mac_rlc_status_resp; } +//----------------------------------------------------------------------------- +rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const sub_frame_t subframeP, + const eNB_flag_t enb_flagP, + const logical_chan_id_t channel_idP) +{ + //----------------------------------------------------------------------------- + rlc_buffer_occupancy_t mac_rlc_buffer_occupancy_resp = 0; + rlc_mode_t rlc_mode = RLC_MODE_NONE; + rlc_union_t *rlc_union_p = NULL; + hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; + hashtable_rc_t h_rc; + srb_flag_t srb_flag = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO; + protocol_ctxt_t ctxt; + + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index); + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_GET_BUFFER_OCCUPANCY_IND,VCD_FUNCTION_IN); + + + /* Assumptions : for UE only */ + /* At each TTI, Buffer Occupancy is first computed in mac_rlc_status_ind called by MAC ue_scheduler() function */ + /* Then this function is called during MAC multiplexing ue_get_sdu(), and it may be call several times for the same bearer if it is in AM mode and there are several PDU types to transmit */ + AssertFatal(enb_flagP == FALSE,"RLC Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%d\n", channel_idP); + + + key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag); + + + h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p); + + if (h_rc == HASH_TABLE_OK) { + rlc_mode = rlc_union_p->mode; + } else { + rlc_mode = RLC_MODE_NONE; + //LOG_W(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP); + //LOG_D(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP); + } + + switch (rlc_mode) { + case RLC_MODE_AM: + mac_rlc_buffer_occupancy_resp = rlc_am_get_buffer_occupancy_in_bytes(&ctxt, &rlc_union_p->rlc.am); + break; + + case RLC_MODE_UM: + mac_rlc_buffer_occupancy_resp = rlc_um_get_buffer_occupancy(&rlc_union_p->rlc.um); + break; + + default: + mac_rlc_buffer_occupancy_resp = 0 ; + } + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_GET_BUFFER_OCCUPANCY_IND,VCD_FUNCTION_OUT); + + return mac_rlc_buffer_occupancy_resp; +} + + diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c index 8304752e8e2b91811afc03185099cdaff7e0724e..a45838603e324f9aa3adb0fc78e67f3a0adce011 100644 --- a/openair2/LAYER2/RLC/rlc_rrc.c +++ b/openair2/LAYER2/RLC/rlc_rrc.c @@ -42,7 +42,7 @@ #include "SRB-ToAddMod.h" #include "SRB-ToAddModList.h" #include "DL-UM-RLC.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "PMCH-InfoList-r9.h" #endif @@ -53,7 +53,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP const SRB_ToAddModList_t * const srb2add_listP, const DRB_ToAddModList_t * const drb2add_listP, const DRB_ToReleaseList_t * const drb2release_listP -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) ,const PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP #endif ) @@ -69,7 +69,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP rlc_union_t *rlc_union_p = NULL; hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_rc; -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) int i, j; MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL; MBMS_SessionInfo_r9_t *MBMS_SessionInfo_p = NULL; @@ -344,7 +344,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP } } -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) if (pmch_InfoList_r9_pP != NULL) { for (i=0; i<pmch_InfoList_r9_pP->list.count; i++) { @@ -487,7 +487,7 @@ rlc_op_status_t rrc_rlc_remove_rlc ( hash_key_t key_lcid = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_lcid_rc; rlc_union_t *rlc_union_p = NULL; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) rlc_mbms_id_t *mbms_id_p = NULL; #endif #ifdef OAI_EMU @@ -498,7 +498,7 @@ rlc_op_status_t rrc_rlc_remove_rlc ( /* for no gcc warnings */ (void)lcid; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flagP == TRUE) { if (ctxt_pP->enb_flag) { @@ -592,7 +592,7 @@ rlc_union_t* rrc_rlc_add_rlc ( hash_key_t key_lcid = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_lcid_rc; rlc_union_t *rlc_union_p = NULL; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) rlc_mbms_id_t *mbms_id_p = NULL; logical_chan_id_t lcid = 0; #endif @@ -608,7 +608,7 @@ rlc_union_t* rrc_rlc_add_rlc ( AssertFatal (chan_idP < RLC_MAX_LC, "LC id is too high (%u/%d)!\n", chan_idP, RLC_MAX_LC); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flagP == TRUE) { if (ctxt_pP->enb_flag) { @@ -650,7 +650,7 @@ rlc_union_t* rrc_rlc_add_rlc ( h_lcid_rc = hashtable_insert(rlc_coll_p, key_lcid, rlc_union_p); if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) { -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flagP == TRUE) { LOG_I(RLC, PROTOCOL_CTXT_FMT" RLC service id %u session id %u rrc_rlc_add_rlc\n", diff --git a/openair2/NAS/DRIVER/CELLULAR/NASMT/nasmt_device.c b/openair2/NAS/DRIVER/CELLULAR/NASMT/nasmt_device.c index 7a8bd0f86788e94e7dccc31c20098806fa9c8710..77b3c28165f879f182c6204398cd3e0685fe1ca7 100644 --- a/openair2/NAS/DRIVER/CELLULAR/NASMT/nasmt_device.c +++ b/openair2/NAS/DRIVER/CELLULAR/NASMT/nasmt_device.c @@ -233,9 +233,12 @@ int nasmt_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } // End debug information - netif_stop_queue(dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif #ifdef NAS_DEBUG_SEND_DETAIL printk("nasmt_hard_start_xmit: step 1\n"); #endif @@ -307,7 +310,11 @@ void nasmt_tx_timeout(struct net_device *dev) printk("nasmt_tx_timeout: begin\n"); //((struct nas_priv *)(dev->priv))->stats.tx_errors++; (gpriv->stats).tx_errors++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif netif_wake_queue(dev); printk("nasmt_tx_timeout: transmit timed out %s\n",dev->name); } diff --git a/openair2/NAS/DRIVER/CELLULAR/NASRG/nasrg_device.c b/openair2/NAS/DRIVER/CELLULAR/NASRG/nasrg_device.c index aaaa95754dcabe873ad8aea0e2a4fcbf18d52b77..970600de214357157b9546eec561d02a846de770 100644 --- a/openair2/NAS/DRIVER/CELLULAR/NASRG/nasrg_device.c +++ b/openair2/NAS/DRIVER/CELLULAR/NASRG/nasrg_device.c @@ -226,7 +226,11 @@ int nasrg_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) // End debug information netif_stop_queue(dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif #ifdef NAS_DEBUG_SEND_DETAIL printk("nasrg_hard_start_xmit: step 1\n"); #endif @@ -296,7 +300,11 @@ void nasrg_tx_timeout(struct net_device *dev) printk("nasrg_tx_timeout: begin\n"); // ((struct nas_priv *)(dev->priv))->stats.tx_errors++; (gpriv->stats).tx_errors++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif netif_wake_queue(dev); printk("nasrg_tx_timeout: transmit timed out %s\n",dev->name); } diff --git a/openair2/NETWORK_DRIVER/LITE/device.c b/openair2/NETWORK_DRIVER/LITE/device.c index 9579ebf249cecd5665a10c8493b4a96c45c4ab6a..616af5e14550c47e52f38c91b292ff64806bcab8 100644 --- a/openair2/NETWORK_DRIVER/LITE/device.c +++ b/openair2/NETWORK_DRIVER/LITE/device.c @@ -255,7 +255,11 @@ int oai_nw_drv_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) // End debug information netif_stop_queue(dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif #ifdef OAI_DRV_DEBUG_DEVICE printk("[OAI_IP_DRV][%s] step 1\n", __FUNCTION__); #endif @@ -328,7 +332,11 @@ void oai_nw_drv_tx_timeout(struct net_device *dev) printk("[OAI_IP_DRV][%s] begin\n", __FUNCTION__); // (struct oai_nw_drv_priv *)(dev->priv)->stats.tx_errors++; (priv->stats).tx_errors++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif netif_wake_queue(dev); printk("[OAI_IP_DRV][%s] transmit timed out %s\n", __FUNCTION__,dev->name); } diff --git a/openair2/NETWORK_DRIVER/MESH/RB_TOOL/rb_tool.c b/openair2/NETWORK_DRIVER/MESH/RB_TOOL/rb_tool.c index 5222a4a4b86cd60c2e867b68548915510c83a2ac..24dfcaf61ec098c3c85269a40945fdb52296cbdd 100644 --- a/openair2/NETWORK_DRIVER/MESH/RB_TOOL/rb_tool.c +++ b/openair2/NETWORK_DRIVER/MESH/RB_TOOL/rb_tool.c @@ -36,7 +36,8 @@ #include <sys/socket.h> #include <sys/un.h> #include <sys/time.h> - +#include <sys/ioctl.h> +#include <ctype.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -109,7 +110,7 @@ void IAL_NAS_ioctl_init(int inst) { struct nas_msg_statistic_reply *msgrep; - int err,rc; + int err; sprintf(gifr.name, "oai%d",inst); @@ -132,7 +133,6 @@ void IAL_NAS_ioctl_init(int inst) if (err<0) { printf("IOCTL error, err=%d\n",err); - rc = -1; } printf("tx_packets = %u, rx_packets = %u\n", msgrep->tx_packets, msgrep->rx_packets); @@ -151,19 +151,13 @@ void IAL_NAS_ioctl_init(int inst) int main(int argc,char **argv) //--------------------------------------------------------------------------- { - int done = 0, rc = 0, meas_polling_counter = 0; - fd_set readfds; - struct timeval tv; - int i = 0; int err = 0; - char * buffer; int c = 0; int action=0,rbset=0,cxset=0,instset=0,saddr_ipv4set=0,saddr_ipv6set=0,daddr_ipv4set=0,daddr_ipv6set=0,dscpset=0,mpls_outlabelset=0,mpls_inlabelset=0; char rb[100],cx[100],dscp[100],inst[100],mpls_outgoinglabel[100],mpls_incominglabel[100]; - int index = 0; struct nas_msg_rb_establishment_request *msgreq = NULL; struct nas_msg_class_add_request *msgreq_class = NULL; - in_addr_t saddr_ipv4,daddr_ipv4; + in_addr_t saddr_ipv4 = 0,daddr_ipv4 = 0; struct in6_addr saddr_ipv6,daddr_ipv6; unsigned int mpls_outlabel=0,mpls_inlabel=0; @@ -213,15 +207,21 @@ int main(int argc,char **argv) mpls_inlabelset=1; break; - case 's': - inet_aton(optarg,&saddr_ipv4); + case 's': { + struct in_addr a; + inet_aton(optarg,&a); + saddr_ipv4 = a.s_addr; saddr_ipv4set = 1; break; + } - case 't': - inet_aton(optarg,&daddr_ipv4); + case 't': { + struct in_addr a; + inet_aton(optarg,&a); + daddr_ipv4 = a.s_addr; daddr_ipv4set = 1; break; + } case 'x': printf("IPv6: %s\n",optarg); @@ -303,7 +303,7 @@ int main(int argc,char **argv) if (action == ADD_RB) { gifr.type = NAS_MSG_RB_ESTABLISHMENT_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); - + if (err == -1) perror("ioctl"); if (saddr_ipv4set == 1) { @@ -329,6 +329,7 @@ int main(int argc,char **argv) gifr.type = NAS_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); @@ -340,6 +341,7 @@ int main(int argc,char **argv) msgreq_class->saddr.ipv4 = daddr_ipv4; gifr.type = NAS_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); } if (saddr_ipv6set == 1) { @@ -370,6 +372,7 @@ int main(int argc,char **argv) gifr.type = NAS_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); @@ -380,6 +383,7 @@ int main(int argc,char **argv) memcpy(&msgreq_class->saddr.ipv6,&daddr_ipv6,16); gifr.type = NAS_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); } @@ -411,6 +415,7 @@ int main(int argc,char **argv) gifr.type = NAS_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); msgreq_class->rab_id = atoi(rb); msgreq_class->lcr = atoi(cx); @@ -430,12 +435,14 @@ int main(int argc,char **argv) gifr.type = NAS_MSG_CLASS_ADD_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); } } else if (action == DEL_RB) { gifr.type = NAS_MSG_RB_RELEASE_REQUEST; err=ioctl(fd, NAS_IOCTL_RRM, &gifr); + if (err == -1) perror("ioctl"); } diff --git a/openair2/NETWORK_DRIVER/MESH/classifier.c b/openair2/NETWORK_DRIVER/MESH/classifier.c index a982faac46b04266fd3cd94ed1b32b7e104b76ce..f47d63008c947d74a098ba58ee9e07f2983ee87e 100644 --- a/openair2/NETWORK_DRIVER/MESH/classifier.c +++ b/openair2/NETWORK_DRIVER/MESH/classifier.c @@ -605,12 +605,12 @@ void nas_CLASS_send(struct sk_buff *skb,int inst) //--------------------------------------------------------------------------- struct classifier_entity *p, *sp; uint8_t *protocolh,version; - uint8_t protocol, dscp, exp,label; + uint8_t protocol, dscp /*, exp,label*/ ; uint16_t classref; struct cx_entity *cx; - unsigned int i; + //unsigned int i; - unsigned int router_adv = 0; + //unsigned int router_adv = 0; struct net_device *dev=nasdev[inst]; struct nas_priv *gpriv=netdev_priv(dev); @@ -790,7 +790,7 @@ void nas_CLASS_send(struct sk_buff *skb,int inst) dscp, sprotocol, sp->classref, sfct, sp->rab_id); #endif - sp->fct(skb, cx, sp,inst); + sp->fct(skb, cx, sp,inst, NULL); } // if classifier entry match found @@ -808,7 +808,7 @@ void nas_CLASS_send(struct sk_buff *skb,int inst) if (no_connection == 1) printk("NAS_CLASS_SEND: no corresponding connection, so the message is dropped\n"); -#endif NAS_DEBUG_CLASS +#endif /* NAS_DEBUG_CLASS */ // } // while loop over connections diff --git a/openair2/NETWORK_DRIVER/MESH/common.c b/openair2/NETWORK_DRIVER/MESH/common.c index 0a4e3ddfed975167f8ca74180707c8e8b3e61de6..95e4cf1fc2662f890192e8e106e7a53e7ae62a7f 100644 --- a/openair2/NETWORK_DRIVER/MESH/common.c +++ b/openair2/NETWORK_DRIVER/MESH/common.c @@ -59,14 +59,14 @@ void nas_COMMON_receive(uint16_t dlen, struct nas_priv *gpriv=netdev_priv(nasdev[inst]); uint32_t odaddr,osaddr; - int i; + //int i; unsigned char protocol; - unsigned char *addr,*daddr,*saddr,*ifaddr,sn; + unsigned char /**addr,*/ *daddr,*saddr,*ifaddr /*,sn*/; - struct udphdr *uh; - struct tcphdr *th; + //struct udphdr *uh; + //struct tcphdr *th; uint16_t *cksum,check; struct iphdr *network_header; @@ -321,10 +321,9 @@ void nas_COMMON_receive(uint16_t dlen, //--------------------------------------------------------------------------- // Delete the data -void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *sp,int inst) +void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *sp,int inst,struct nas_priv *gpriv) { struct nas_priv *priv=netdev_priv(nasdev[inst]); - //--------------------------------------------------------------------------- ++priv->stats.tx_dropped; } @@ -332,7 +331,7 @@ void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct class //--------------------------------------------------------------------------- // Request the transfer of data (QoS SAP) -void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst) +void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct pdcp_data_req_header_s pdcph; @@ -341,7 +340,7 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct class int i; #endif unsigned int bytes_wrote; - unsigned char j; + //unsigned char j; // Start debug information #ifdef NAS_DEBUG_SEND printk("NAS_COMMON_QOS_SEND - inst %d begin \n",inst); @@ -596,7 +595,7 @@ struct rb_entity *nas_COMMON_search_rb(struct cx_entity *cx, nasRadioBearerId_t struct classifier_entity *nas_COMMON_search_class_for_rb(nasRadioBearerId_t rab_id,struct nas_priv *priv) { - struct rb_entity *rb; + //struct rb_entity *rb; int dscp; struct classifier_entity *rclass; diff --git a/openair2/NETWORK_DRIVER/MESH/device.c b/openair2/NETWORK_DRIVER/MESH/device.c index f28b41fc6889ef0e531c9eed210e51261c55a7fe..393fe9f9e01fe3ffd4fe863a7b693ab5d309e4f8 100644 --- a/openair2/NETWORK_DRIVER/MESH/device.c +++ b/openair2/NETWORK_DRIVER/MESH/device.c @@ -124,11 +124,8 @@ void *nas_interrupt(void) int nas_open(struct net_device *dev) { //--------------------------------------------------------------------------- - struct nas_priv *priv=netdev_priv(dev); - printk("OPEN: begin\n"); // MOD_INC_USE_COUNT; - // Address has already been set at init #ifndef PDCP_USE_NETLINK @@ -250,7 +247,11 @@ int nas_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) // End debug information netif_stop_queue(dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif #ifdef DEBUG_DEVICE printk("HARD_START_XMIT: step 1\n"); #endif @@ -311,7 +312,11 @@ void nas_tx_timeout(struct net_device *dev) printk("TX_TIMEOUT: begin\n"); // (struct nas_priv *)(dev->priv)->stats.tx_errors++; (priv->stats).tx_errors++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev); +#else dev->trans_start = jiffies; +#endif netif_wake_queue(dev); printk("TX_TIMEOUT: transmit timed out %s\n",dev->name); } @@ -406,8 +411,8 @@ void nas_init(struct net_device *dev) nas_TOOL_imei2iid(IMEI, dev->dev_addr);// IMEI to device address (for stateless autoconfiguration address) nas_TOOL_imei2iid(IMEI, (uint8_t *)priv->cx[0].iid6); #else - nas_TOOL_imei2iid(nas_IMEI, dev->dev_addr);// IMEI to device address (for stateless autoconfiguration address) - nas_TOOL_imei2iid(nas_IMEI, (uint8_t *)priv->cx[0].iid6); + nas_TOOL_imei2iid((uint8_t *)nas_IMEI, dev->dev_addr); // IMEI to device address (for stateless autoconfiguration address) + nas_TOOL_imei2iid((uint8_t *)nas_IMEI, (uint8_t *)priv->cx[0].iid6); #endif // this is more appropriate for user space soft realtime emulation #else @@ -478,8 +483,8 @@ int init_module (void) if (nasdev[inst]) { nas_mesh_init(inst); //memcpy(nasdev[inst]->dev_addr,&nas_IMEI[0],8); - nas_TOOL_imei2iid(nas_IMEI, nasdev[inst]->dev_addr);// IMEI to device address (for stateless autoconfiguration address) - nas_TOOL_imei2iid(nas_IMEI, (uint8_t *)priv->cx[0].iid6); + nas_TOOL_imei2iid((uint8_t *)nas_IMEI, nasdev[inst]->dev_addr);// IMEI to device address (for stateless autoconfiguration address) + nas_TOOL_imei2iid((uint8_t *)nas_IMEI, (uint8_t *)priv->cx[0].iid6); // TO HAVE DIFFERENT HW @ ((unsigned char*)nasdev[inst]->dev_addr)[7] = ((unsigned char*)nasdev[inst]->dev_addr)[7] + (unsigned char)inst + 1; printk("Setting HW addr for INST %d to : %X%X\n",inst,*((unsigned int *)&nasdev[inst]->dev_addr[0]),*((unsigned int *)&nasdev[inst]->dev_addr[4])); diff --git a/openair2/NETWORK_DRIVER/MESH/ioctl.c b/openair2/NETWORK_DRIVER/MESH/ioctl.c index 7d4bb10b1f841dc50c2be8d2bf065760d66a3cf7..913fcc1e755e2ac9dd658d5fc1d34c1ee1146053 100644 --- a/openair2/NETWORK_DRIVER/MESH/ioctl.c +++ b/openair2/NETWORK_DRIVER/MESH/ioctl.c @@ -739,7 +739,6 @@ void nas_set_msg_imei_reply(struct nas_msg_l2id_reply *msgrep, //--------------------------------------------------------------------------- struct cx_entity *cx; int lcr=0; // Temp lcr->mt =0 - int i; cx=nas_COMMON_search_cx(lcr,priv); @@ -853,7 +852,7 @@ int nas_CTL_ioctl(struct net_device *dev, //--------------------------------------------------------------------------- void nas_CTL_send(struct sk_buff *skb, struct cx_entity *cx, - struct classifier_entity *gc) + struct classifier_entity *gc, int inst, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- printk("NAS_CTL_SEND - void \n"); diff --git a/openair2/NETWORK_DRIVER/MESH/local.h b/openair2/NETWORK_DRIVER/MESH/local.h index 8db2b550b0defecb5d42fb671f94818174f102b1..0e0a581cbc9590a0cda18fe29caba28a9e91e5b5 100644 --- a/openair2/NETWORK_DRIVER/MESH/local.h +++ b/openair2/NETWORK_DRIVER/MESH/local.h @@ -98,6 +98,26 @@ struct cx_entity { int provider_id[MAX_MEASURE_NB]; }; +//#define NAS_RETRY_LIMIT_DEFAULT 5 + +struct nas_priv { + int irq; + struct timer_list timer; + spinlock_t lock; + struct net_device_stats stats; + uint8_t retry_limit; + uint32_t timer_establishment; + uint32_t timer_release; + struct cx_entity cx[NAS_CX_MAX]; + struct classifier_entity *rclassifier[NAS_DSCP_MAX]; // receive classifier + uint16_t nrclassifier; + int sap[NAS_SAPI_MAX]; + struct sock *nl_sk; + uint8_t nlmsg[NAS_MAX_LENGTH+sizeof(struct nlmsghdr)]; + uint8_t xbuffer[NAS_MAX_LENGTH]; // transmition buffer + uint8_t rbuffer[NAS_MAX_LENGTH]; // reception buffer +}; + struct classifier_entity { uint32_t classref; @@ -122,29 +142,7 @@ struct classifier_entity { struct rb_entity *rb_rx; //pointer to rb_entity for receiving (in case of forwarding rule) nasRadioBearerId_t rab_id; // RAB identification for sending nasRadioBearerId_t rab_id_rx; // RAB identification for receiving (in case of forwarding rule) - void (*fct)(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst); -}; - - - -//#define NAS_RETRY_LIMIT_DEFAULT 5 - -struct nas_priv { - int irq; - struct timer_list timer; - spinlock_t lock; - struct net_device_stats stats; - uint8_t retry_limit; - uint32_t timer_establishment; - uint32_t timer_release; - struct cx_entity cx[NAS_CX_MAX]; - struct classifier_entity *rclassifier[NAS_DSCP_MAX]; // receive classifier - uint16_t nrclassifier; - int sap[NAS_SAPI_MAX]; - struct sock *nl_sk; - uint8_t nlmsg[NAS_MAX_LENGTH+sizeof(struct nlmsghdr)]; - uint8_t xbuffer[NAS_MAX_LENGTH]; // transmition buffer - uint8_t rbuffer[NAS_MAX_LENGTH]; // reception buffer + void (*fct)(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst, struct nas_priv *gpriv); }; struct ipversion { diff --git a/openair2/NETWORK_DRIVER/MESH/mesh.c b/openair2/NETWORK_DRIVER/MESH/mesh.c index e934a6eb9501e60114d7d4112faf9c795d7d32ed..e2cf3bcf0a0e31ad350de7ee56040030e5cdc560 100644 --- a/openair2/NETWORK_DRIVER/MESH/mesh.c +++ b/openair2/NETWORK_DRIVER/MESH/mesh.c @@ -155,9 +155,10 @@ void nas_mesh_start_default_sclassifier(struct cx_entity *cx,struct rb_entity *r } //--------------------------------------------------------------------------- -void nas_mesh_timer(unsigned long data,struct nas_priv *gpriv) +void nas_mesh_timer(unsigned long data) { //--------------------------------------------------------------------------- + struct nas_priv *gpriv=(struct nas_priv *) data; uint8_t cxi; struct cx_entity *cx; struct rb_entity *rb; @@ -168,7 +169,7 @@ void nas_mesh_timer(unsigned long data,struct nas_priv *gpriv) (gpriv->timer).function=nas_mesh_timer; (gpriv->timer).expires=jiffies+NAS_TIMER_TICK; - (gpriv->timer).data=0L; + (gpriv->timer).data=data; return; @@ -381,11 +382,12 @@ int nas_mesh_DC_send_cx_release_request(struct cx_entity *cx, void nas_mesh_DC_send_sig_data_request(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc, + int inst, struct nas_priv *gpriv) { //--------------------------------------------------------------------------- struct nas_ue_dc_element *p; - char data_type = 'A'; + //char data_type = 'A'; int bytes_wrote=0; // Start debug information @@ -464,7 +466,7 @@ void nas_mesh_DC_send_peer_sig_data_request(struct cx_entity *cx, uint8_t sig_ca struct nas_ue_dc_element *p; uint8_t nas_data[10]; unsigned int nas_length; - char data_type = 'Z'; + //char data_type = 'Z'; int bytes_wrote=0; // Start debug information diff --git a/openair2/NETWORK_DRIVER/MESH/netlink.c b/openair2/NETWORK_DRIVER/MESH/netlink.c index 3ce6cf6ebe764337d50e6d49946eb258513435d7..8d40a9d965bc890f04e70f6fae7c1a0ebb9c5656 100644 --- a/openair2/NETWORK_DRIVER/MESH/netlink.c +++ b/openair2/NETWORK_DRIVER/MESH/netlink.c @@ -50,7 +50,7 @@ static struct sock *nas_nl_sk = NULL; static int exit_netlink_thread=0; -static int nas_netlink_rx_thread(void *); +//static int nas_netlink_rx_thread(void *); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) struct netlink_kernel_cfg oai_netlink_cfg; #endif @@ -76,7 +76,7 @@ static void nas_nl_data_ready (struct sk_buff *skb) //nasmesh_unlock(); struct nlmsghdr *nlh = NULL; - int j; + //int j; if (skb) { diff --git a/openair2/NETWORK_DRIVER/MESH/proto_extern.h b/openair2/NETWORK_DRIVER/MESH/proto_extern.h index 4c0b89f60fdec3c67ea3b3e97a4af6c8e73273ea..a362876f834fa8227619063bb0f54c0d93e004f9 100644 --- a/openair2/NETWORK_DRIVER/MESH/proto_extern.h +++ b/openair2/NETWORK_DRIVER/MESH/proto_extern.h @@ -96,7 +96,7 @@ void nas_COMMON_receive(unsigned short dlen, */ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, - struct classifier_entity *gc,int inst); + struct classifier_entity *gc,int inst, struct nas_priv *gpriv); /** \fn void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst) @@ -108,7 +108,7 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, */ void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, - struct classifier_entity *gc,int inst); + struct classifier_entity *gc,int inst, struct nas_priv *gpriv); #ifndef PDCP_USE_NETLINK /** @@ -195,19 +195,18 @@ void nas_mesh_init(int inst //!< Instance ID ); -void nas_mesh_timer(unsigned long data, - struct nas_priv *gpriv); +void nas_mesh_timer(unsigned long data); int nas_mesh_DC_receive(struct cx_entity *cx,struct nas_priv *gpriv); int nas_mesh_GC_receive(struct nas_priv *gpriv); int nas_mesh_DC_send_cx_establish_request(struct cx_entity *cx,struct nas_priv *gpriv); int nas_mesh_DC_send_cx_release_request(struct cx_entity *cx,struct nas_priv *gpriv); -void nas_mesh_DC_send_sig_data_request(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,struct nas_priv *gpriv); +void nas_mesh_DC_send_sig_data_request(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst, struct nas_priv *gpriv); // iocontrol.c void nas_CTL_send(struct sk_buff *skb, struct cx_entity *cx, - struct classifier_entity *gc); + struct classifier_entity *gc,int inst, struct nas_priv *gpriv); //int nas_CTL_receive_authentication(struct ipv6hdr *iph, struct cx-entity *cx, unsigned char sapi); int nas_CTL_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c index 86968015975e09e05e37a6639bdcf6eee3cd6cff..8c3e4557d36d109efcf7198a41a033a906897108 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/common.c +++ b/openair2/NETWORK_DRIVER/UE_IP/common.c @@ -123,9 +123,7 @@ skb_p->mark = rb_idP; // LG TEST skb_p->ip_summed = CHECKSUM_NONE; skb_p->ip_summed = CHECKSUM_UNNECESSARY; - - - ipv_p = (struct ipversion*)((void*)&(skb_p->data[hard_header_len])); + ipv_p = (ipversion_t *)((void *)&(skb_p->data[hard_header_len])); switch (ipv_p->version) { @@ -345,7 +343,7 @@ void ue_ip_common_wireless2ip(struct nlmsghdr *nlh_pP) ue_ip_common_class_wireless2ip(pdcph_p->data_size, (unsigned char *)NLMSG_DATA(nlh_pP) + UE_IP_PDCPH_SIZE, - 1, //pdcph_p->inst, + pdcph_p->inst, pdcph_p->rb_id); } diff --git a/openair2/NETWORK_DRIVER/UE_IP/constant.h b/openair2/NETWORK_DRIVER/UE_IP/constant.h index 9b4017773b0c84726ecc1846f50bfbe617b86b51..42fd0b6303c0bcaca9665e0eae52c135a31d6a0b 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/constant.h +++ b/openair2/NETWORK_DRIVER/UE_IP/constant.h @@ -19,6 +19,7 @@ * contact@openairinterface.org */ +#include "openairinterface5g_limits.h" #ifndef _UE_IP_CST #define _UE_IP_CST @@ -51,7 +52,7 @@ -#define UE_IP_NB_INSTANCES_MAX 8 +#define UE_IP_NB_INSTANCES_MAX NUMBER_OF_UE_MAX #endif diff --git a/openair2/NETWORK_DRIVER/UE_IP/device.c b/openair2/NETWORK_DRIVER/UE_IP/device.c index cfd734286222ceeade640147df282ac8a8c32ab5..a4f714d4c5537218896398f5fd6d92dbee44a12e 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/device.c +++ b/openair2/NETWORK_DRIVER/UE_IP/device.c @@ -243,7 +243,11 @@ int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP) // End debug information netif_stop_queue(dev_pP); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev_pP); +#else dev_pP->trans_start = jiffies; +#endif #ifdef OAI_DRV_DEBUG_DEVICE printk("[UE_IP_DRV][%s] step 1\n", __FUNCTION__); #endif @@ -315,7 +319,11 @@ void ue_ip_tx_timeout(struct net_device *dev_pP) printk("[UE_IP_DRV][%s] begin\n", __FUNCTION__); // (ue_ip_priv_t *)(dev_pP->priv_p)->stats.tx_errors++; (priv_p->stats).tx_errors++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + netif_trans_update(dev_pP); +#else dev_pP->trans_start = jiffies; +#endif netif_wake_queue(dev_pP); printk("[UE_IP_DRV][%s] transmit timed out %s\n", __FUNCTION__,dev_pP->name); } diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h index 497325205491c028ec944dc80d68b929e24b1bea..effc4c78776ccf0a1de61a991be44a525fdaf609 100644 --- a/openair2/PHY_INTERFACE/defs.h +++ b/openair2/PHY_INTERFACE/defs.h @@ -112,7 +112,7 @@ typedef struct { AdditionalSpectrumEmission_t *additionalSpectrumEmission, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// Configure Common PHY parameters from SIB13 void (*phy_config_sib13_eNB)(module_id_t Mod_id,int CC_id, int mbsfn_Area_idx, long mbsfn_AreaId_r9); @@ -127,7 +127,7 @@ typedef struct { void (*phy_config_dedicated_eNB)(module_id_t Mod_id,int CC_id,rnti_t rnti, struct PhysicalConfigDedicated *physicalConfigDedicated); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// Get MCH sdu and corresponding MCS for particular MBSFN subframe MCH_PDU* (*get_mch_sdu)(module_id_t Mod_id, int CC_id, frame_t frameP,sub_frame_t subframe); #endif @@ -154,7 +154,7 @@ typedef struct { /// Send a received DLSCH sdu to MAC void (*ue_send_sdu)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,sub_frame_t subframe,uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// Send a received MCH sdu to MAC void (*ue_send_mch_sdu)(module_id_t Mod_id,uint8_t CC_id, frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index,uint8_t sync_area); @@ -170,7 +170,7 @@ typedef struct { PRACH_RESOURCES_t* (*ue_get_rach)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t Msg3_flag,sub_frame_t subframe); /// Process Random-Access Response - uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index); + uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index, uint8_t* selected_rar_buffer); /// Get SR payload (0,1) from UE MAC uint32_t (*ue_get_SR)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe); @@ -202,7 +202,7 @@ typedef struct { AdditionalSpectrumEmission_t *additionalSpectrumEmission, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /// Configure Common PHY parameters from SIB13 void (*phy_config_sib13_ue)(uint8_t Mod_id,int CC_id, uint8_t eNB_index,int mbsfn_Area_idx, long mbsfn_AreaId_r9); diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c index fa5a4d64097aad4195791c7e366f70626eb6ecfe..64734cac9a554a967069021d2c32e7a45b70d8df 100644 --- a/openair2/RRC/LITE/L2_interface.c +++ b/openair2/RRC/LITE/L2_interface.c @@ -222,7 +222,7 @@ mac_rrc_data_req( return (Sdu_size); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if((Srb_id & RAB_OFFSET) == MCCH) { if(eNB_rrc_inst[Mod_idP].carrier[CC_id].MCCH_MESS[mbsfn_sync_area].Active==0) { @@ -281,7 +281,7 @@ mac_rrc_data_req( //return(0); } -#endif //Rel10 +#endif //Rel10 || Rel14 } else { //This is an UE LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %d\n",Mod_idP,frameP,Srb_id); @@ -428,7 +428,7 @@ mac_rrc_data_ind( } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if ((srb_idP & RAB_OFFSET) == MCCH) { LOG_T(RRC,"[UE %d] Frame %d: Received SDU on MBSFN sync area %d for MCCH on SRB %d from eNB %d\n", @@ -459,7 +459,7 @@ mac_rrc_data_ind( #endif } -#endif // Rel10 +#endif // Rel10 || Rel14 } else { // This is an eNB Srb_info = &eNB_rrc_inst[module_idP].carrier[CC_id].Srb0; diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c index b4290e8b9de4c61219a8580f9b67f7a9d881c5ae..c5cfbdd2dc45050f0d7f83d017a2ef11106a7eac 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c @@ -58,7 +58,7 @@ #include "RRCConnectionSetup.h" #include "SRB-ToAddModList.h" #include "DRB-ToAddModList.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MCCH-Message.h" //#define MRB1 1 #endif @@ -614,7 +614,7 @@ uint8_t do_SIB23(uint8_t Mod_id, BCCH_DL_SCH_Message_t *bcch_message, SystemInformationBlockType2_t **sib2, SystemInformationBlockType3_t **sib3 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , SystemInformationBlockType13_r9_t **sib13, uint8_t MBMS_flag @@ -625,7 +625,7 @@ uint8_t do_SIB23(uint8_t Mod_id, ) { struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib2_part,*sib3_part; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib13_part; MBSFN_SubframeConfigList_t *MBSFNSubframeConfigList; MBSFN_AreaInfoList_r9_t *MBSFNArea_list; @@ -650,7 +650,7 @@ uint8_t do_SIB23(uint8_t Mod_id, exit(-1); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) LOG_I(RRC,"[eNB %d] Configuration SIB2/3, MBMS = %d\n", Mod_id, MBMS_flag); #else LOG_I(RRC,"[eNB %d] Configuration SIB2/3\n", Mod_id); @@ -666,7 +666,7 @@ uint8_t do_SIB23(uint8_t Mod_id, *sib2 = &sib2_part->choice.sib2; *sib3 = &sib3_part->choice.sib3; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flag > 0) { sib13_part = CALLOC(1,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member)); @@ -680,7 +680,7 @@ uint8_t do_SIB23(uint8_t Mod_id, // sib2 (*sib2)->ac_BarringInfo = NULL; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #if 0 (*sib2)->ssac_BarringForMMTEL_Voice_r9 = NULL; (*sib2)->ssac_BarringForMMTEL_Video_r9 = NULL; @@ -769,7 +769,7 @@ uint8_t do_SIB23(uint8_t Mod_id, = configuration->pucch_nRB_CQI[CC_id]; (*sib2)->radioResourceConfigCommon.pucch_ConfigCommon.nCS_AN = configuration->pucch_nCS_AN[CC_id]; -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) (*sib2)->radioResourceConfigCommon.pucch_ConfigCommon.n1PUCCH_AN = configuration->pucch_n1_AN[CC_id]; #endif @@ -929,7 +929,7 @@ uint8_t do_SIB23(uint8_t Mod_id, (*sib2)->freqInfo.ul_Bandwidth = NULL; // (*sib2)->mbsfn_SubframeConfigList = NULL; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flag > 0) { LOG_I(RRC,"Adding MBSFN subframe Configuration 1 to SIB2\n"); @@ -985,7 +985,7 @@ uint8_t do_SIB23(uint8_t Mod_id, (*sib2)->timeAlignmentTimerCommon=TimeAlignmentTimer_infinity;//TimeAlignmentTimer_sf5120; /// (*SIB3) -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (*sib3)->ext1 = NULL; #if 0 (*sib3)->s_IntraSearch_v920=NULL; @@ -1020,7 +1020,7 @@ uint8_t do_SIB23(uint8_t Mod_id, // SIB13 // fill in all elements of SIB13 if present -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flag > 0 ) { // Notification for mcch change @@ -1102,7 +1102,7 @@ uint8_t do_SIB23(uint8_t Mod_id, sib2_part); ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib3_part); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (MBMS_flag > 0) { ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list,sib13_part); @@ -1505,7 +1505,10 @@ do_RRCConnectionSetup( // PDSCH //assign_enum(&physicalConfigDedicated2->pdsch_ConfigDedicated->p_a, // PDSCH_ConfigDedicated__p_a_dB0); - physicalConfigDedicated2->pdsch_ConfigDedicated->p_a= PDSCH_ConfigDedicated__p_a_dB0; + if (frame_parms->nb_antenna_ports_eNB==2) + physicalConfigDedicated2->pdsch_ConfigDedicated->p_a= PDSCH_ConfigDedicated__p_a_dB_3; + else + physicalConfigDedicated2->pdsch_ConfigDedicated->p_a= PDSCH_ConfigDedicated__p_a_dB0; // PUCCH physicalConfigDedicated2->pucch_ConfigDedicated->ackNackRepetition.present=PUCCH_ConfigDedicated__ackNackRepetition_PR_release; @@ -1560,7 +1563,7 @@ do_RRCConnectionSetup( // CQI ReportConfig physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic=CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic)); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) *physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic= CQI_ReportModeAperiodic_rm30; #else *physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic=CQI_ReportConfig__cqi_ReportModeAperiodic_rm30; // HLC CQI, no PMI @@ -1590,8 +1593,33 @@ do_RRCConnectionSetup( SoundingRS_UL_ConfigDedicated__setup__srs_HoppingBandwidth_hbw0; physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition=0; physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.duration=1; - physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=45; - physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb=0; + if (frame_parms->frame_type==FDD) { + if (enb_properties.properties[ctxt_pP->module_id]->srs_SubframeConfig[CC_id]!=0) + LOG_W(RRC,"This code has been optimized for SRS Subframe Config 0, but current config is %d. Expect undefined behaviour!\n", + enb_properties.properties[ctxt_pP->module_id]->srs_SubframeConfig[CC_id]); + if (ue_context_pP->local_uid >=20) + LOG_W(RRC,"This code has been optimized for up to 10 UEs, but current UE_id is %d. Expect undefined behaviour!\n", + ue_context_pP->local_uid); + //the current code will allow for 20 UEs - to be revised for more + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=7+ue_context_pP->local_uid/2; + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb= ue_context_pP->local_uid%2; + } + else { + if (enb_properties.properties[ctxt_pP->module_id]->srs_SubframeConfig[CC_id]!=7) { + LOG_W(RRC,"This code has been optimized for SRS Subframe Config 7 and TDD config 3, but current configs are %d and %d. Expect undefined behaviour!\n", + enb_properties.properties[ctxt_pP->module_id]->srs_SubframeConfig[CC_id], + enb_properties.properties[ctxt_pP->module_id]->tdd_config[CC_id]); + } + if (ue_context_pP->local_uid >=6) + LOG_W(RRC,"This code has been optimized for up to 6 UEs, but current UE_id is %d. Expect undefined behaviour!\n", + ue_context_pP->local_uid); + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=17+ue_context_pP->local_uid/2; + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb= ue_context_pP->local_uid%2; + } + LOG_W(RRC,"local UID %d, srs ConfigIndex %d, TransmissionComb %d\n",ue_context_pP->local_uid, + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex, + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb); + physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift= SoundingRS_UL_ConfigDedicated__setup__cyclicShift_cs0; } @@ -1773,7 +1801,7 @@ do_SecurityModeCommand( SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8; // the two following information could be based on the mod_id dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm - = (e_SecurityAlgorithmConfig__cipheringAlgorithm)cipheringAlgorithm; + = (CipheringAlgorithm_r12_t)cipheringAlgorithm; dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm = (e_SecurityAlgorithmConfig__integrityProtAlgorithm)integrityProtAlgorithm; @@ -1926,7 +1954,7 @@ do_RRCConnectionReconfiguration( struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , SCellToAddMod_r10_t *SCell_config #endif ) @@ -2221,7 +2249,7 @@ uint8_t do_RRCConnectionRelease( uint8_t TMGI[5] = {4,3,2,1,0};//TMGI is a string of octet, ref. TS 24.008 fig. 10.5.4a -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) uint8_t do_MBSFNAreaConfig(uint8_t Mod_id, LTE_DL_FRAME_PARMS *frame_parms, uint8_t sync_area, @@ -2393,7 +2421,7 @@ uint8_t do_MeasurementReport(uint8_t Mod_id, uint8_t *buffer,int measid,int phy_ sizeof(*measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.nonCriticalExtension)); measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.measResults.measId=measid; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.measResults.measResultPCell.rsrpResult=rsrp_s; measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.measResults.measResultPCell.rsrqResult=rsrq_s; #else diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.h b/openair2/RRC/LITE/MESSAGES/asn1_msg.h index 881a778030294a2d1e9262c57fedd43dd6576f64..4466457075a0566e380ed62dbac679d46ed365d9 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.h @@ -93,7 +93,7 @@ uint8_t do_SIB23(uint8_t Mod_id, BCCH_DL_SCH_Message_t *systemInformation, SystemInformationBlockType2_t **sib2, SystemInformationBlockType3_t **sib3 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , SystemInformationBlockType13_r9_t **sib13, uint8_t MBMS_flag @@ -197,7 +197,7 @@ do_RRCConnectionReconfiguration( RSRP_Range_t *rsrp, C_RNTI_t *cba_rnti, struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList* dedicatedInfoNASList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , SCellToAddMod_r10_t *SCell_config #endif ); @@ -238,7 +238,7 @@ uint8_t do_RRCConnectionRelease(uint8_t Mod_id, uint8_t *buffer,int Transaction_ * @returns Size of encoded bit stream in bytes */ uint8_t do_MCCHMessage(uint8_t *buffer); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /*** * \brief Generate an MCCH-Message (eNB). This routine configures MBSFNAreaConfiguration (PMCH-InfoList and Subframe Allocation for MBMS data) * @param buffer Pointer to PER-encoded ASN.1 description of MCCH-Message PDU diff --git a/openair2/RRC/LITE/MESSAGES/asn1c/ASN1_files/RRC-e10.asn b/openair2/RRC/LITE/MESSAGES/asn1c/ASN1_files/RRC-e10.asn new file mode 100644 index 0000000000000000000000000000000000000000..cb13f30c0eef108b1d09e1bd68cbbab424c332cc --- /dev/null +++ b/openair2/RRC/LITE/MESSAGES/asn1c/ASN1_files/RRC-e10.asn @@ -0,0 +1,12010 @@ + +EUTRA-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + + +BCCH-BCH-Message ::= SEQUENCE { + message BCCH-BCH-MessageType +} + +BCCH-BCH-MessageType ::= MasterInformationBlock + + +BCCH-DL-SCH-Message ::= SEQUENCE { + message BCCH-DL-SCH-MessageType +} + +BCCH-DL-SCH-MessageType ::= CHOICE { + c1 CHOICE { + systemInformation SystemInformation, + systemInformationBlockType1 SystemInformationBlockType1 + }, + messageClassExtension SEQUENCE {} +} + + +BCCH-DL-SCH-Message-BR ::= SEQUENCE { + message BCCH-DL-SCH-MessageType-BR-r13 +} + +BCCH-DL-SCH-MessageType-BR-r13 ::= CHOICE { + c1 CHOICE { + systemInformation-BR-r13 SystemInformation-BR-r13, + systemInformationBlockType1-BR-r13 SystemInformationBlockType1-BR-r13 + }, + messageClassExtension SEQUENCE {} +} + + +MCCH-Message ::= SEQUENCE { + message MCCH-MessageType +} + +MCCH-MessageType ::= CHOICE { + c1 CHOICE { + mbsfnAreaConfiguration-r9 MBSFNAreaConfiguration-r9 + }, + later CHOICE { + c2 CHOICE{ + mbmsCountingRequest-r10 MBMSCountingRequest-r10 + }, + messageClassExtension SEQUENCE {} + } +} + + +PCCH-Message ::= SEQUENCE { + message PCCH-MessageType +} + +PCCH-MessageType ::= CHOICE { + c1 CHOICE { + paging Paging + }, + messageClassExtension SEQUENCE {} +} + + +DL-CCCH-Message ::= SEQUENCE { + message DL-CCCH-MessageType +} + +DL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcConnectionReestablishment RRCConnectionReestablishment, + rrcConnectionReestablishmentReject RRCConnectionReestablishmentReject, + rrcConnectionReject RRCConnectionReject, + rrcConnectionSetup RRCConnectionSetup + }, + messageClassExtension SEQUENCE {} +} + + +DL-DCCH-Message ::= SEQUENCE { + message DL-DCCH-MessageType +} + +DL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + csfbParametersResponseCDMA2000 CSFBParametersResponseCDMA2000, + dlInformationTransfer DLInformationTransfer, + handoverFromEUTRAPreparationRequest HandoverFromEUTRAPreparationRequest, + mobilityFromEUTRACommand MobilityFromEUTRACommand, + rrcConnectionReconfiguration RRCConnectionReconfiguration, + rrcConnectionRelease RRCConnectionRelease, + securityModeCommand SecurityModeCommand, + ueCapabilityEnquiry UECapabilityEnquiry, + counterCheck CounterCheck, + ueInformationRequest-r9 UEInformationRequest-r9, + loggedMeasurementConfiguration-r10 LoggedMeasurementConfiguration-r10, + rnReconfiguration-r10 RNReconfiguration-r10, + rrcConnectionResume-r13 RRCConnectionResume-r13, + spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + + +UL-CCCH-Message ::= SEQUENCE { + message UL-CCCH-MessageType +} + +UL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcConnectionReestablishmentRequest RRCConnectionReestablishmentRequest, + rrcConnectionRequest RRCConnectionRequest + }, + messageClassExtension CHOICE { + c2 CHOICE { + rrcConnectionResumeRequest-r13 RRCConnectionResumeRequest-r13 + }, + messageClassExtensionFuture-r13 SEQUENCE {} + } +} + + +UL-DCCH-Message ::= SEQUENCE { + message UL-DCCH-MessageType +} + +UL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + csfbParametersRequestCDMA2000 CSFBParametersRequestCDMA2000, + measurementReport MeasurementReport, + rrcConnectionReconfigurationComplete RRCConnectionReconfigurationComplete, + rrcConnectionReestablishmentComplete RRCConnectionReestablishmentComplete, + rrcConnectionSetupComplete RRCConnectionSetupComplete, + securityModeComplete SecurityModeComplete, + securityModeFailure SecurityModeFailure, + ueCapabilityInformation UECapabilityInformation, + ulHandoverPreparationTransfer ULHandoverPreparationTransfer, + ulInformationTransfer ULInformationTransfer, + counterCheckResponse CounterCheckResponse, + ueInformationResponse-r9 UEInformationResponse-r9, + proximityIndication-r9 ProximityIndication-r9, + rnReconfigurationComplete-r10 RNReconfigurationComplete-r10, + mbmsCountingResponse-r10 MBMSCountingResponse-r10, + interFreqRSTDMeasurementIndication-r10 InterFreqRSTDMeasurementIndication-r10 + }, + messageClassExtension CHOICE { + c2 CHOICE { + ueAssistanceInformation-r11 UEAssistanceInformation-r11, + inDeviceCoexIndication-r11 InDeviceCoexIndication-r11, + mbmsInterestIndication-r11 MBMSInterestIndication-r11, + scgFailureInformation-r12 SCGFailureInformation-r12, + sidelinkUEInformation-r12 SidelinkUEInformation-r12, + wlanConnectionStatusReport-r13 WLANConnectionStatusReport-r13, + rrcConnectionResumeComplete-r13 RRCConnectionResumeComplete-r13, + spare9 NULL, spare8 NULL, spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtensionFuture-r11 SEQUENCE {} + } +} + + +SC-MCCH-Message-r13 ::= SEQUENCE { + message SC-MCCH-MessageType-r13 +} + + +SC-MCCH-MessageType-r13 ::= CHOICE { + c1 CHOICE { + scptmConfiguration-r13 SCPTMConfiguration-r13 + }, + messageClassExtension SEQUENCE {} +} + + +CounterCheck ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + counterCheck-r8 CounterCheck-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheck-r8-IEs ::= SEQUENCE { + drb-CountMSB-InfoList DRB-CountMSB-InfoList, + nonCriticalExtension CounterCheck-v8a0-IEs OPTIONAL +} + +CounterCheck-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +DRB-CountMSB-InfoList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-CountMSB-Info + +DRB-CountMSB-Info ::= SEQUENCE { + drb-Identity DRB-Identity, + countMSB-Uplink INTEGER(0..33554431), + countMSB-Downlink INTEGER(0..33554431) +} + + +CounterCheckResponse ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheckResponse-r8 CounterCheckResponse-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheckResponse-r8-IEs ::= SEQUENCE { + drb-CountInfoList DRB-CountInfoList, + nonCriticalExtension CounterCheckResponse-v8a0-IEs OPTIONAL +} + +CounterCheckResponse-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +DRB-CountInfoList ::= SEQUENCE (SIZE (0..maxDRB)) OF DRB-CountInfo + +DRB-CountInfo ::= SEQUENCE { + drb-Identity DRB-Identity, + count-Uplink INTEGER(0..4294967295), + count-Downlink INTEGER(0..4294967295) +} + + +CSFBParametersRequestCDMA2000 ::= SEQUENCE { + criticalExtensions CHOICE { + csfbParametersRequestCDMA2000-r8 CSFBParametersRequestCDMA2000-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CSFBParametersRequestCDMA2000-r8-IEs ::= SEQUENCE { + nonCriticalExtension CSFBParametersRequestCDMA2000-v8a0-IEs OPTIONAL +} + +CSFBParametersRequestCDMA2000-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +CSFBParametersResponseCDMA2000 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + csfbParametersResponseCDMA2000-r8 CSFBParametersResponseCDMA2000-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CSFBParametersResponseCDMA2000-r8-IEs ::= SEQUENCE { + rand RAND-CDMA2000, + mobilityParameters MobilityParametersCDMA2000, + nonCriticalExtension CSFBParametersResponseCDMA2000-v8a0-IEs OPTIONAL +} + +CSFBParametersResponseCDMA2000-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +DLInformationTransfer ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + dlInformationTransfer-r8 DLInformationTransfer-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransfer-r8-IEs ::= SEQUENCE { + dedicatedInfoType CHOICE { + dedicatedInfoNAS DedicatedInfoNAS, + dedicatedInfoCDMA2000-1XRTT DedicatedInfoCDMA2000, + dedicatedInfoCDMA2000-HRPD DedicatedInfoCDMA2000 + }, + nonCriticalExtension DLInformationTransfer-v8a0-IEs OPTIONAL +} + +DLInformationTransfer-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +HandoverFromEUTRAPreparationRequest ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + handoverFromEUTRAPreparationRequest-r8 + HandoverFromEUTRAPreparationRequest-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverFromEUTRAPreparationRequest-r8-IEs ::= SEQUENCE { + cdma2000-Type CDMA2000-Type, + rand RAND-CDMA2000 OPTIONAL, -- Cond cdma2000-Type + mobilityParameters MobilityParametersCDMA2000 OPTIONAL, -- Cond cdma2000-Type + nonCriticalExtension HandoverFromEUTRAPreparationRequest-v890-IEs OPTIONAL +} + +HandoverFromEUTRAPreparationRequest-v890-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension HandoverFromEUTRAPreparationRequest-v920-IEs OPTIONAL +} + +HandoverFromEUTRAPreparationRequest-v920-IEs ::= SEQUENCE { + concurrPrepCDMA2000-HRPD-r9 BOOLEAN OPTIONAL, -- Cond cdma2000-Type + nonCriticalExtension HandoverFromEUTRAPreparationRequest-v1020-IEs OPTIONAL +} + +HandoverFromEUTRAPreparationRequest-v1020-IEs ::= SEQUENCE { + dualRxTxRedirectIndicator-r10 ENUMERATED {true} OPTIONAL, -- Cond cdma2000-1XRTT + redirectCarrierCDMA2000-1XRTT-r10 CarrierFreqCDMA2000 OPTIONAL, -- Cond dualRxTxRedirect + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +InDeviceCoexIndication-r11 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + inDeviceCoexIndication-r11 InDeviceCoexIndication-r11-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +InDeviceCoexIndication-r11-IEs ::= SEQUENCE { + affectedCarrierFreqList-r11 AffectedCarrierFreqList-r11 OPTIONAL, + tdm-AssistanceInfo-r11 TDM-AssistanceInfo-r11 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension InDeviceCoexIndication-v11d0-IEs OPTIONAL +} + +InDeviceCoexIndication-v11d0-IEs ::= SEQUENCE { + ul-CA-AssistanceInfo-r11 SEQUENCE { + affectedCarrierFreqCombList-r11 AffectedCarrierFreqCombList-r11 OPTIONAL, + victimSystemType-r11 VictimSystemType-r11 + } OPTIONAL, + nonCriticalExtension InDeviceCoexIndication-v1310-IEs OPTIONAL +} + +InDeviceCoexIndication-v1310-IEs ::= SEQUENCE { + affectedCarrierFreqList-v1310 AffectedCarrierFreqList-v1310 OPTIONAL, + affectedCarrierFreqCombList-r13 AffectedCarrierFreqCombList-r13 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +AffectedCarrierFreqList-r11 ::= SEQUENCE (SIZE (1..maxFreqIDC-r11)) OF AffectedCarrierFreq-r11 + +AffectedCarrierFreqList-v1310 ::= SEQUENCE (SIZE (1..maxFreqIDC-r11)) OF AffectedCarrierFreq-v1310 + +AffectedCarrierFreq-r11 ::= SEQUENCE { + carrierFreq-r11 MeasObjectId, + interferenceDirection-r11 ENUMERATED {eutra, other, both, spare} +} + +AffectedCarrierFreq-v1310 ::= SEQUENCE { + carrierFreq-v1310 MeasObjectId-v1310 OPTIONAL +} + +AffectedCarrierFreqCombList-r11 ::= SEQUENCE (SIZE (1..maxCombIDC-r11)) OF AffectedCarrierFreqComb-r11 + +AffectedCarrierFreqCombList-r13 ::= SEQUENCE (SIZE (1..maxCombIDC-r11)) OF AffectedCarrierFreqComb-r13 + +AffectedCarrierFreqComb-r11 ::= SEQUENCE (SIZE (2..maxServCell-r10)) OF MeasObjectId + +AffectedCarrierFreqComb-r13 ::= SEQUENCE (SIZE (2..maxServCell-r13)) OF MeasObjectId-r13 + +TDM-AssistanceInfo-r11 ::= CHOICE { + drx-AssistanceInfo-r11 SEQUENCE { + drx-CycleLength-r11 ENUMERATED {sf40, sf64, sf80, sf128, sf160, + sf256, spare2, spare1}, + drx-Offset-r11 INTEGER (0..255) OPTIONAL, + drx-ActiveTime-r11 ENUMERATED {sf20, sf30, sf40, sf60, sf80, + sf100, spare2, spare1} + }, + idc-SubframePatternList-r11 IDC-SubframePatternList-r11, + ... +} + +IDC-SubframePatternList-r11 ::= SEQUENCE (SIZE (1..maxSubframePatternIDC-r11)) OF IDC-SubframePattern-r11 + +IDC-SubframePattern-r11 ::= CHOICE { + subframePatternFDD-r11 BIT STRING (SIZE (4)), + subframePatternTDD-r11 CHOICE { + subframeConfig0-r11 BIT STRING (SIZE (70)), + subframeConfig1-5-r11 BIT STRING (SIZE (10)), + subframeConfig6-r11 BIT STRING (SIZE (60)) + }, + ... +} + +VictimSystemType-r11 ::= SEQUENCE { + gps-r11 ENUMERATED {true} OPTIONAL, + glonass-r11 ENUMERATED {true} OPTIONAL, + bds-r11 ENUMERATED {true} OPTIONAL, + galileo-r11 ENUMERATED {true} OPTIONAL, + wlan-r11 ENUMERATED {true} OPTIONAL, + bluetooth-r11 ENUMERATED {true} OPTIONAL +} + + +InterFreqRSTDMeasurementIndication-r10 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + interFreqRSTDMeasurementIndication-r10 InterFreqRSTDMeasurementIndication-r10-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +InterFreqRSTDMeasurementIndication-r10-IEs ::= SEQUENCE { + rstd-InterFreqIndication-r10 CHOICE { + start SEQUENCE { + rstd-InterFreqInfoList-r10 RSTD-InterFreqInfoList-r10 + }, + stop NULL + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RSTD-InterFreqInfoList-r10 ::= SEQUENCE (SIZE(1..maxRSTD-Freq-r10)) OF RSTD-InterFreqInfo-r10 + +RSTD-InterFreqInfo-r10 ::= SEQUENCE { + carrierFreq-r10 ARFCN-ValueEUTRA, + measPRS-Offset-r10 INTEGER (0..39), + ..., + [[ carrierFreq-v1090 ARFCN-ValueEUTRA-v9e0 OPTIONAL + ]] +} + + +LoggedMeasurementConfiguration-r10 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + loggedMeasurementConfiguration-r10 LoggedMeasurementConfiguration-r10-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + + +LoggedMeasurementConfiguration-r10-IEs ::= SEQUENCE { + traceReference-r10 TraceReference-r10, + traceRecordingSessionRef-r10 OCTET STRING (SIZE (2)), + tce-Id-r10 OCTET STRING (SIZE (1)), + absoluteTimeInfo-r10 AbsoluteTimeInfo-r10, + areaConfiguration-r10 AreaConfiguration-r10 OPTIONAL, -- Need OR + loggingDuration-r10 LoggingDuration-r10, + loggingInterval-r10 LoggingInterval-r10, + nonCriticalExtension LoggedMeasurementConfiguration-v1080-IEs OPTIONAL +} + +LoggedMeasurementConfiguration-v1080-IEs ::= SEQUENCE { + lateNonCriticalExtension-r10 OCTET STRING OPTIONAL, + nonCriticalExtension LoggedMeasurementConfiguration-v1130-IEs OPTIONAL +} + +LoggedMeasurementConfiguration-v1130-IEs ::= SEQUENCE { + plmn-IdentityList-r11 PLMN-IdentityList3-r11 OPTIONAL, -- Need OR + areaConfiguration-v1130 AreaConfiguration-v1130 OPTIONAL, -- Need OR + nonCriticalExtension LoggedMeasurementConfiguration-v1250-IEs OPTIONAL +} + +LoggedMeasurementConfiguration-v1250-IEs ::= SEQUENCE { + targetMBSFN-AreaList-r12 TargetMBSFN-AreaList-r12 OPTIONAL, -- Need OP + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +TargetMBSFN-AreaList-r12 ::= SEQUENCE (SIZE (0..maxMBSFN-Area)) OF TargetMBSFN-Area-r12 + +TargetMBSFN-Area-r12 ::= SEQUENCE { + mbsfn-AreaId-r12 MBSFN-AreaId-r12 OPTIONAL, -- Need OR + carrierFreq-r12 ARFCN-ValueEUTRA-r9, + ... +} + + +MasterInformationBlock ::= SEQUENCE { + dl-Bandwidth ENUMERATED { + n6, n15, n25, n50, n75, n100}, + phich-Config PHICH-Config, + systemFrameNumber BIT STRING (SIZE (8)), + schedulingInfoSIB1-BR-r13 INTEGER (0..31), + spare BIT STRING (SIZE (5)) +} + + + +MBMSCountingRequest-r10 ::= SEQUENCE { + countingRequestList-r10 CountingRequestList-r10, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +CountingRequestList-r10 ::= SEQUENCE (SIZE (1..maxServiceCount)) OF CountingRequestInfo-r10 + +CountingRequestInfo-r10 ::= SEQUENCE { + tmgi-r10 TMGI-r9, + ... +} + + +MBMSCountingResponse-r10 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + countingResponse-r10 MBMSCountingResponse-r10-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MBMSCountingResponse-r10-IEs ::= SEQUENCE { + mbsfn-AreaIndex-r10 INTEGER (0..maxMBSFN-Area-1) OPTIONAL, + countingResponseList-r10 CountingResponseList-r10 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +CountingResponseList-r10 ::= SEQUENCE (SIZE (1..maxServiceCount)) OF CountingResponseInfo-r10 + +CountingResponseInfo-r10 ::= SEQUENCE { + countingResponseService-r10 INTEGER (0..maxServiceCount-1), + ... +} + + +MBMSInterestIndication-r11 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + interestIndication-r11 MBMSInterestIndication-r11-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MBMSInterestIndication-r11-IEs ::= SEQUENCE { + mbms-FreqList-r11 CarrierFreqListMBMS-r11 OPTIONAL, + mbms-Priority-r11 ENUMERATED {true} OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MBMSInterestIndication-v1310-IEs OPTIONAL +} + +MBMSInterestIndication-v1310-IEs ::= SEQUENCE { + mbms-Services-r13 MBMS-ServiceList-r13 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +MBSFNAreaConfiguration-r9 ::= SEQUENCE { + commonSF-Alloc-r9 CommonSF-AllocPatternList-r9, + commonSF-AllocPeriod-r9 ENUMERATED { + rf4, rf8, rf16, rf32, rf64, rf128, rf256}, + pmch-InfoList-r9 PMCH-InfoList-r9, + nonCriticalExtension MBSFNAreaConfiguration-v930-IEs OPTIONAL +} + +MBSFNAreaConfiguration-v930-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MBSFNAreaConfiguration-v1250-IEs OPTIONAL +} + +MBSFNAreaConfiguration-v1250-IEs ::= SEQUENCE { + pmch-InfoListExt-r12 PMCH-InfoListExt-r12 OPTIONAL, -- Need OR + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +CommonSF-AllocPatternList-r9 ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF MBSFN-SubframeConfig + + +MeasurementReport ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + measurementReport-r8 MeasurementReport-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementReport-r8-IEs ::= SEQUENCE { + measResults MeasResults, + nonCriticalExtension MeasurementReport-v8a0-IEs OPTIONAL +} + +MeasurementReport-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +MobilityFromEUTRACommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + mobilityFromEUTRACommand-r8 MobilityFromEUTRACommand-r8-IEs, + mobilityFromEUTRACommand-r9 MobilityFromEUTRACommand-r9-IEs, + spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MobilityFromEUTRACommand-r8-IEs ::= SEQUENCE { + cs-FallbackIndicator BOOLEAN, + purpose CHOICE{ + handover Handover, + cellChangeOrder CellChangeOrder + }, + nonCriticalExtension MobilityFromEUTRACommand-v8a0-IEs OPTIONAL +} + +MobilityFromEUTRACommand-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MobilityFromEUTRACommand-v8d0-IEs OPTIONAL +} + +MobilityFromEUTRACommand-v8d0-IEs ::= SEQUENCE { + bandIndicator BandIndicatorGERAN OPTIONAL, -- Cond GERAN + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MobilityFromEUTRACommand-r9-IEs ::= SEQUENCE { + cs-FallbackIndicator BOOLEAN, + purpose CHOICE{ + handover Handover, + cellChangeOrder CellChangeOrder, + e-CSFB-r9 E-CSFB-r9, + ... + }, + nonCriticalExtension MobilityFromEUTRACommand-v930-IEs OPTIONAL +} + +MobilityFromEUTRACommand-v930-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MobilityFromEUTRACommand-v960-IEs OPTIONAL +} + +MobilityFromEUTRACommand-v960-IEs ::= SEQUENCE { + bandIndicator BandIndicatorGERAN OPTIONAL, -- Cond GERAN + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +Handover ::= SEQUENCE { + targetRAT-Type ENUMERATED { + utra, geran, cdma2000-1XRTT, cdma2000-HRPD, + spare4, spare3, spare2, spare1, ...}, + targetRAT-MessageContainer OCTET STRING, + nas-SecurityParamFromEUTRA OCTET STRING (SIZE (1)) OPTIONAL, -- Cond UTRAGERAN + systemInformation SI-OrPSI-GERAN OPTIONAL -- Cond PSHO +} + +CellChangeOrder ::= SEQUENCE { + t304 ENUMERATED { + ms100, ms200, ms500, ms1000, + ms2000, ms4000, ms8000, ms10000-v1310}, + targetRAT-Type CHOICE { + geran SEQUENCE { + physCellId PhysCellIdGERAN, + carrierFreq CarrierFreqGERAN, + networkControlOrder BIT STRING (SIZE (2)) OPTIONAL, -- Need OP + systemInformation SI-OrPSI-GERAN OPTIONAL -- Need OP + }, + ... + } +} + +SI-OrPSI-GERAN ::= CHOICE { + si SystemInfoListGERAN, + psi SystemInfoListGERAN +} + +E-CSFB-r9 ::= SEQUENCE { + messageContCDMA2000-1XRTT-r9 OCTET STRING OPTIONAL, -- Need ON + mobilityCDMA2000-HRPD-r9 ENUMERATED { + handover, redirection + } OPTIONAL, -- Need OP + messageContCDMA2000-HRPD-r9 OCTET STRING OPTIONAL, -- Cond concHO + redirectCarrierCDMA2000-HRPD-r9 CarrierFreqCDMA2000 OPTIONAL -- Cond concRedir +} + + +Paging ::= SEQUENCE { + pagingRecordList PagingRecordList OPTIONAL, -- Need ON + systemInfoModification ENUMERATED {true} OPTIONAL, -- Need ON + etws-Indication ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension Paging-v890-IEs OPTIONAL +} + +Paging-v890-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension Paging-v920-IEs OPTIONAL +} + +Paging-v920-IEs ::= SEQUENCE { + cmas-Indication-r9 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension Paging-v1130-IEs OPTIONAL +} + +Paging-v1130-IEs ::= SEQUENCE { + eab-ParamModification-r11 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension Paging-v1310-IEs OPTIONAL +} + +Paging-v1310-IEs ::= SEQUENCE { + redistributionIndication-r13 ENUMERATED {true} OPTIONAL, --Need ON + systemInfoModification-eDRX-r13 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +PagingRecordList ::= SEQUENCE (SIZE (1..maxPageRec)) OF PagingRecord + +PagingRecord ::= SEQUENCE { + ue-Identity PagingUE-Identity, + cn-Domain ENUMERATED {ps, cs}, + ... +} + +PagingUE-Identity ::= CHOICE { + s-TMSI S-TMSI, + imsi IMSI, + ... +} + +IMSI ::= SEQUENCE (SIZE (6..21)) OF IMSI-Digit + +IMSI-Digit ::= INTEGER (0..9) + + +ProximityIndication-r9 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + proximityIndication-r9 ProximityIndication-r9-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ProximityIndication-r9-IEs ::= SEQUENCE { + type-r9 ENUMERATED {entering, leaving}, + carrierFreq-r9 CHOICE { + eutra-r9 ARFCN-ValueEUTRA, + utra-r9 ARFCN-ValueUTRA, + ..., + eutra2-v9e0 ARFCN-ValueEUTRA-v9e0 + }, + nonCriticalExtension ProximityIndication-v930-IEs OPTIONAL +} + +ProximityIndication-v930-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RNReconfiguration-r10 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rnReconfiguration-r10 RNReconfiguration-r10-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RNReconfiguration-r10-IEs ::= SEQUENCE { + rn-SystemInfo-r10 RN-SystemInfo-r10 OPTIONAL, -- Need ON + rn-SubframeConfig-r10 RN-SubframeConfig-r10 OPTIONAL, -- Need ON + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RN-SystemInfo-r10 ::= SEQUENCE { + systemInformationBlockType1-r10 OCTET STRING (CONTAINING SystemInformationBlockType1) OPTIONAL, -- Need ON + systemInformationBlockType2-r10 SystemInformationBlockType2 OPTIONAL, -- Need ON + ... +} + + +RNReconfigurationComplete-r10 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + rnReconfigurationComplete-r10 RNReconfigurationComplete-r10-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RNReconfigurationComplete-r10-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReconfiguration ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + rrcConnectionReconfiguration-r8 RRCConnectionReconfiguration-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReconfiguration-r8-IEs ::= SEQUENCE { + measConfig MeasConfig OPTIONAL, -- Need ON + mobilityControlInfo MobilityControlInfo OPTIONAL, -- Cond HO + dedicatedInfoNASList SEQUENCE (SIZE(1..maxDRB)) OF + DedicatedInfoNAS OPTIONAL, -- Cond nonHO + radioResourceConfigDedicated RadioResourceConfigDedicated OPTIONAL, -- Cond HO-toEUTRA + securityConfigHO SecurityConfigHO OPTIONAL, -- Cond HO + nonCriticalExtension RRCConnectionReconfiguration-v890-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v890-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING (CONTAINING RRCConnectionReconfiguration-v8m0-IEs) OPTIONAL, + nonCriticalExtension RRCConnectionReconfiguration-v920-IEs OPTIONAL +} + +-- Late non-critical extensions: +RRCConnectionReconfiguration-v8m0-IEs ::= SEQUENCE { + -- Following field is only for pre REL-10 late non-critical extensions + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCConnectionReconfiguration-v10i0-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v10i0-IEs ::= SEQUENCE { + antennaInfoDedicatedPCell-v10i0 AntennaInfoDedicated-v10i0 OPTIONAL, -- Need ON + -- Following field is only for late non-critical extensions from REL-10 + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non-critical extensions: +RRCConnectionReconfiguration-v920-IEs ::= SEQUENCE { + otherConfig-r9 OtherConfig-r9 OPTIONAL, -- Need ON + fullConfig-r9 ENUMERATED {true} OPTIONAL, -- Cond HO-Reestab + nonCriticalExtension RRCConnectionReconfiguration-v1020-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v1020-IEs ::= SEQUENCE { + sCellToReleaseList-r10 SCellToReleaseList-r10 OPTIONAL, -- Need ON + sCellToAddModList-r10 SCellToAddModList-r10 OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionReconfiguration-v1130-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v1130-IEs ::= SEQUENCE { + systemInformationBlockType1Dedicated-r11 OCTET STRING (CONTAINING SystemInformationBlockType1) OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionReconfiguration-v1250-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v1250-IEs ::= SEQUENCE { + wlan-OffloadInfo-r12 CHOICE { + release NULL, + setup SEQUENCE { + wlan-OffloadConfigDedicated-r12 WLAN-OffloadConfig-r12, + t350-r12 ENUMERATED {min5, min10, min20, min30, min60, + min120, min180, spare1} OPTIONAL -- Need OR + } + } OPTIONAL, -- Need ON + scg-Configuration-r12 SCG-Configuration-r12 OPTIONAL, -- Cond nonFullConfig + sl-SyncTxControl-r12 SL-SyncTxControl-r12 OPTIONAL, -- Need ON + sl-DiscConfig-r12 SL-DiscConfig-r12 OPTIONAL, -- Need ON + sl-CommConfig-r12 SL-CommConfig-r12 OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionReconfiguration-v1310-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v1310-IEs ::= SEQUENCE { + sCellToReleaseListExt-r13 SCellToReleaseListExt-r13 OPTIONAL, -- Need ON + sCellToAddModListExt-r13 SCellToAddModListExt-r13 OPTIONAL, -- Need ON + lwa-Configuration-r13 LWA-Configuration-r13 OPTIONAL, -- Need ON + lwip-Configuration-r13 LWIP-Configuration-r13 OPTIONAL, -- Need ON + rclwi-Configuration-r13 RCLWI-Configuration-r13 OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionReconfiguration-v14x0-IEs OPTIONAL +} + +RRCConnectionReconfiguration-v14x0-IEs ::= SEQUENCE { + sl-V2X-ConfigDedicated-r14 SL-V2X-ConfigDedicated-r14 OPTIONAL, -- Need ON + sCellToAddModListExt-v14xy SCellToAddModListExt-v14xy OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SL-SyncTxControl-r12 ::= SEQUENCE { + networkControlledSyncTx-r12 ENUMERATED {on, off} OPTIONAL -- Need OP +} + +PSCellToAddMod-r12 ::= SEQUENCE { + sCellIndex-r12 SCellIndex-r10, + cellIdentification-r12 SEQUENCE { + physCellId-r12 PhysCellId, + dl-CarrierFreq-r12 ARFCN-ValueEUTRA-r9 + } OPTIONAL, -- Cond SCellAdd + radioResourceConfigCommonPSCell-r12 RadioResourceConfigCommonPSCell-r12 OPTIONAL, -- Cond SCellAdd + radioResourceConfigDedicatedPSCell-r12 RadioResourceConfigDedicatedPSCell-r12 OPTIONAL, -- Cond SCellAdd2 + ..., + [[ antennaInfoDedicatedPSCell-v1280 AntennaInfoDedicated-v10i0 OPTIONAL -- Need ON + ]], + [[ sCellIndex-r13 SCellIndex-r13 OPTIONAL -- Need ON + ]] +} + +PowerCoordinationInfo-r12 ::= SEQUENCE { + p-MeNB-r12 INTEGER (1..16), + p-SeNB-r12 INTEGER (1..16), + powerControlMode-r12 INTEGER (1..2) +} + +SCellToAddModList-r10 ::= SEQUENCE (SIZE (1..maxSCell-r10)) OF SCellToAddMod-r10 + +SCellToAddModListExt-r13 ::= SEQUENCE (SIZE (1..maxSCell-r13)) OF SCellToAddModExt-r13 + +SCellToAddModListExt-v14xy ::= SEQUENCE (SIZE (1..maxSCell-r13)) OF SCellToAddModExt-v14xy + +SCellToAddMod-r10 ::= SEQUENCE { + sCellIndex-r10 SCellIndex-r10, + cellIdentification-r10 SEQUENCE { + physCellId-r10 PhysCellId, + dl-CarrierFreq-r10 ARFCN-ValueEUTRA + } OPTIONAL, -- Cond SCellAdd + radioResourceConfigCommonSCell-r10 RadioResourceConfigCommonSCell-r10 OPTIONAL, -- Cond SCellAdd + radioResourceConfigDedicatedSCell-r10 RadioResourceConfigDedicatedSCell-r10 OPTIONAL, -- Cond SCellAdd2 + ..., + [[ dl-CarrierFreq-v1090 ARFCN-ValueEUTRA-v9e0 OPTIONAL -- Cond EARFCN-max + ]], + [[ antennaInfoDedicatedSCell-v10i0 AntennaInfoDedicated-v10i0 OPTIONAL -- Need ON + ]], + [[ srs-SwitchFromServCellIndex-r14 INTEGER (0.. 31) OPTIONAL -- Need ON + ]] +} + +SCellToAddModExt-r13 ::= SEQUENCE { + sCellIndex-r13 SCellIndex-r13, + cellIdentification-r13 SEQUENCE { + physCellId-r13 PhysCellId, + dl-CarrierFreq-r13 ARFCN-ValueEUTRA-r9 + } OPTIONAL, -- Cond SCellAdd + radioResourceConfigCommonSCell-r13 RadioResourceConfigCommonSCell-r10 OPTIONAL, -- Cond SCellAdd + radioResourceConfigDedicatedSCell-r13 RadioResourceConfigDedicatedSCell-r10 OPTIONAL, -- Cond SCellAdd2 + antennaInfoDedicatedSCell-r13 AntennaInfoDedicated-v10i0 OPTIONAL -- Need ON +} + +SCellToAddModExt-v14xy ::= SEQUENCE { + srs-SwitchFromServCellIndex-r14 INTEGER (0.. 31) OPTIONAL -- Need ON +} + +SCellToReleaseList-r10 ::= SEQUENCE (SIZE (1..maxSCell-r10)) OF SCellIndex-r10 + +SCellToReleaseListExt-r13 ::= SEQUENCE (SIZE (1..maxSCell-r13)) OF SCellIndex-r13 + +SCG-Configuration-r12 ::= CHOICE { + release NULL, + setup SEQUENCE { + scg-ConfigPartMCG-r12 SEQUENCE { + scg-Counter-r12 INTEGER (0.. 65535) OPTIONAL, -- Need ON + powerCoordinationInfo-r12 PowerCoordinationInfo-r12 OPTIONAL, -- Need ON + ... + } OPTIONAL, -- Need ON + scg-ConfigPartSCG-r12 SCG-ConfigPartSCG-r12 OPTIONAL -- Need ON + } +} + +SCG-ConfigPartSCG-r12 ::= SEQUENCE { + radioResourceConfigDedicatedSCG-r12 RadioResourceConfigDedicatedSCG-r12 OPTIONAL, -- Need ON + sCellToReleaseListSCG-r12 SCellToReleaseList-r10 OPTIONAL, -- Need ON + pSCellToAddMod-r12 PSCellToAddMod-r12 OPTIONAL, -- Need ON + sCellToAddModListSCG-r12 SCellToAddModList-r10 OPTIONAL, -- Need ON + mobilityControlInfoSCG-r12 MobilityControlInfoSCG-r12 OPTIONAL, -- Need ON + ..., + [[ + sCellToReleaseListSCG-Ext-r13 SCellToReleaseListExt-r13 OPTIONAL, -- Need ON + sCellToAddModListSCG-Ext-r13 SCellToAddModListExt-r13 OPTIONAL -- Need ON + ]] +} + +SecurityConfigHO ::= SEQUENCE { + handoverType CHOICE { + intraLTE SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Cond fullConfig + keyChangeIndicator BOOLEAN, + nextHopChainingCount NextHopChainingCount + }, + interRAT SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig, + nas-SecurityParamToEUTRA OCTET STRING (SIZE(6)) + } + }, + ... +} + + + +RRCConnectionReconfigurationComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcConnectionReconfigurationComplete-r8 + RRCConnectionReconfigurationComplete-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReconfigurationComplete-r8-IEs ::= SEQUENCE { + nonCriticalExtension RRCConnectionReconfigurationComplete-v8a0-IEs OPTIONAL +} + +RRCConnectionReconfigurationComplete-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCConnectionReconfigurationComplete-v1020-IEs OPTIONAL +} + +RRCConnectionReconfigurationComplete-v1020-IEs ::= SEQUENCE { + rlf-InfoAvailable-r10 ENUMERATED {true} OPTIONAL, + logMeasAvailable-r10 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionReconfigurationComplete-v1130-IEs OPTIONAL +} + +RRCConnectionReconfigurationComplete-v1130-IEs ::= SEQUENCE { + connEstFailInfoAvailable-r11 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionReconfigurationComplete-v1250-IEs OPTIONAL +} + +RRCConnectionReconfigurationComplete-v1250-IEs ::= SEQUENCE { + logMeasAvailableMBSFN-r12 ENUMERATED {true} OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReestablishment ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + rrcConnectionReestablishment-r8 RRCConnectionReestablishment-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishment-r8-IEs ::= SEQUENCE { + radioResourceConfigDedicated RadioResourceConfigDedicated, + nextHopChainingCount NextHopChainingCount, + nonCriticalExtension RRCConnectionReestablishment-v8a0-IEs OPTIONAL +} + +RRCConnectionReestablishment-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReestablishmentComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcConnectionReestablishmentComplete-r8 + RRCConnectionReestablishmentComplete-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishmentComplete-r8-IEs ::= SEQUENCE { + nonCriticalExtension RRCConnectionReestablishmentComplete-v920-IEs OPTIONAL +} + +RRCConnectionReestablishmentComplete-v920-IEs ::= SEQUENCE { + rlf-InfoAvailable-r9 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionReestablishmentComplete-v8a0-IEs OPTIONAL +} + +RRCConnectionReestablishmentComplete-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCConnectionReestablishmentComplete-v1020-IEs OPTIONAL +} + +RRCConnectionReestablishmentComplete-v1020-IEs ::= SEQUENCE { + logMeasAvailable-r10 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionReestablishmentComplete-v1130-IEs OPTIONAL +} + +RRCConnectionReestablishmentComplete-v1130-IEs ::= SEQUENCE { + connEstFailInfoAvailable-r11 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionReestablishmentComplete-v1250-IEs OPTIONAL +} + +RRCConnectionReestablishmentComplete-v1250-IEs ::= SEQUENCE { + logMeasAvailableMBSFN-r12 ENUMERATED {true} OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReestablishmentReject ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionReestablishmentReject-r8 + RRCConnectionReestablishmentReject-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishmentReject-r8-IEs ::= SEQUENCE { + nonCriticalExtension RRCConnectionReestablishmentReject-v8a0-IEs OPTIONAL +} + +RRCConnectionReestablishmentReject-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReestablishmentRequest ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionReestablishmentRequest-r8 + RRCConnectionReestablishmentRequest-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishmentRequest-r8-IEs ::= SEQUENCE { + ue-Identity ReestabUE-Identity, + reestablishmentCause ReestablishmentCause, + spare BIT STRING (SIZE (2)) +} + +ReestabUE-Identity ::= SEQUENCE { + c-RNTI C-RNTI, + physCellId PhysCellId, + shortMAC-I ShortMAC-I +} + +ReestablishmentCause ::= ENUMERATED { + reconfigurationFailure, handoverFailure, + otherFailure, spare1} + + +RRCConnectionReject ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionReject-r8 RRCConnectionReject-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReject-r8-IEs ::= SEQUENCE { + waitTime INTEGER (1..16), + nonCriticalExtension RRCConnectionReject-v8a0-IEs OPTIONAL +} + +RRCConnectionReject-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCConnectionReject-v1020-IEs OPTIONAL +} + +RRCConnectionReject-v1020-IEs ::= SEQUENCE { + extendedWaitTime-r10 INTEGER (1..1800) OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionReject-v1130-IEs OPTIONAL +} + +RRCConnectionReject-v1130-IEs ::= SEQUENCE { + deprioritisationReq-r11 SEQUENCE { + deprioritisationType-r11 ENUMERATED {frequency, e-utra}, + deprioritisationTimer-r11 ENUMERATED {min5, min10, min15, min30} + } OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionReject-v1320-IEs OPTIONAL +} + +RRCConnectionReject-v1320-IEs ::= SEQUENCE { + rrc-SuspendIndication-r13 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionRelease ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionRelease-r8 RRCConnectionRelease-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionRelease-r8-IEs ::= SEQUENCE { + releaseCause ReleaseCause, + redirectedCarrierInfo RedirectedCarrierInfo OPTIONAL, -- Need ON + idleModeMobilityControlInfo IdleModeMobilityControlInfo OPTIONAL, -- Need OP + nonCriticalExtension RRCConnectionRelease-v890-IEs OPTIONAL +} + +RRCConnectionRelease-v890-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING (CONTAINING RRCConnectionRelease-v9e0-IEs) OPTIONAL, + nonCriticalExtension RRCConnectionRelease-v920-IEs OPTIONAL +} + +-- Late non critical extensions +RRCConnectionRelease-v9e0-IEs ::= SEQUENCE { + redirectedCarrierInfo-v9e0 RedirectedCarrierInfo-v9e0 OPTIONAL, -- Cond NoRedirect-r8 + idleModeMobilityControlInfo-v9e0 IdleModeMobilityControlInfo-v9e0 OPTIONAL, -- Cond IdleInfoEUTRA + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non critical extensions +RRCConnectionRelease-v920-IEs ::= SEQUENCE { + cellInfoList-r9 CHOICE { + geran-r9 CellInfoListGERAN-r9, + utra-FDD-r9 CellInfoListUTRA-FDD-r9, + utra-TDD-r9 CellInfoListUTRA-TDD-r9, + ..., + utra-TDD-r10 CellInfoListUTRA-TDD-r10 + } OPTIONAL, -- Cond Redirection + nonCriticalExtension RRCConnectionRelease-v1020-IEs OPTIONAL +} + +RRCConnectionRelease-v1020-IEs ::= SEQUENCE { + extendedWaitTime-r10 INTEGER (1..1800) OPTIONAL, -- Need ON + nonCriticalExtension RRCConnectionRelease-v1320-IEs OPTIONAL +} + +RRCConnectionRelease-v1320-IEs::= SEQUENCE { + resumeIdentity-r13 ResumeIdentity-r13 OPTIONAL, -- Need OR + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +ReleaseCause ::= ENUMERATED {loadBalancingTAUrequired, + other, cs-FallbackHighPriority-v1020, rrc-Suspend-v1320} + +RedirectedCarrierInfo ::= CHOICE { + eutra ARFCN-ValueEUTRA, + geran CarrierFreqsGERAN, + utra-FDD ARFCN-ValueUTRA, + utra-TDD ARFCN-ValueUTRA, + cdma2000-HRPD CarrierFreqCDMA2000, + cdma2000-1xRTT CarrierFreqCDMA2000, + ..., + utra-TDD-r10 CarrierFreqListUTRA-TDD-r10 +} + +RedirectedCarrierInfo-v9e0 ::= SEQUENCE { + eutra-v9e0 ARFCN-ValueEUTRA-v9e0 +} + +CarrierFreqListUTRA-TDD-r10 ::= SEQUENCE (SIZE (1..maxFreqUTRA-TDD-r10)) OF ARFCN-ValueUTRA + +IdleModeMobilityControlInfo ::= SEQUENCE { + freqPriorityListEUTRA FreqPriorityListEUTRA OPTIONAL, -- Need ON + freqPriorityListGERAN FreqsPriorityListGERAN OPTIONAL, -- Need ON + freqPriorityListUTRA-FDD FreqPriorityListUTRA-FDD OPTIONAL, -- Need ON + freqPriorityListUTRA-TDD FreqPriorityListUTRA-TDD OPTIONAL, -- Need ON + bandClassPriorityListHRPD BandClassPriorityListHRPD OPTIONAL, -- Need ON + bandClassPriorityList1XRTT BandClassPriorityList1XRTT OPTIONAL, -- Need ON + t320 ENUMERATED { + min5, min10, min20, min30, min60, min120, min180, + spare1} OPTIONAL, -- Need OR + ..., + [[ freqPriorityListExtEUTRA-r12 FreqPriorityListExtEUTRA-r12 OPTIONAL -- Need ON + ]], + [[ freqPriorityListEUTRA-v1310 FreqPriorityListEUTRA-v1310 OPTIONAL, -- Need ON + freqPriorityListExtEUTRA-v1310 FreqPriorityListExtEUTRA-v1310 OPTIONAL -- Need ON + ]] +} + +IdleModeMobilityControlInfo-v9e0 ::= SEQUENCE { + freqPriorityListEUTRA-v9e0 SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA-v9e0 +} + +FreqPriorityListEUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA + +FreqPriorityListExtEUTRA-r12 ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA-r12 + +FreqPriorityListEUTRA-v1310 ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA-v1310 + +FreqPriorityListExtEUTRA-v1310 ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA-v1310 + +FreqPriorityEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + cellReselectionPriority CellReselectionPriority +} + +FreqPriorityEUTRA-v9e0 ::= SEQUENCE { + carrierFreq-v9e0 ARFCN-ValueEUTRA-v9e0 OPTIONAL -- Cond EARFCN-max +} + +FreqPriorityEUTRA-r12 ::= SEQUENCE { + carrierFreq-r12 ARFCN-ValueEUTRA-r9, + cellReselectionPriority-r12 CellReselectionPriority +} + +FreqPriorityEUTRA-v1310 ::= SEQUENCE { + cellReselectionSubPriority-r13 CellReselectionSubPriority-r13 OPTIONAL -- Need ON +} + +FreqsPriorityListGERAN ::= SEQUENCE (SIZE (1..maxGNFG)) OF FreqsPriorityGERAN + +FreqsPriorityGERAN ::= SEQUENCE { + carrierFreqs CarrierFreqsGERAN, + cellReselectionPriority CellReselectionPriority +} + +FreqPriorityListUTRA-FDD ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF FreqPriorityUTRA-FDD + +FreqPriorityUTRA-FDD ::= SEQUENCE { + carrierFreq ARFCN-ValueUTRA, + cellReselectionPriority CellReselectionPriority +} + +FreqPriorityListUTRA-TDD ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF FreqPriorityUTRA-TDD + +FreqPriorityUTRA-TDD ::= SEQUENCE { + carrierFreq ARFCN-ValueUTRA, + cellReselectionPriority CellReselectionPriority +} + +BandClassPriorityListHRPD ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassPriorityHRPD + +BandClassPriorityHRPD ::= SEQUENCE { + bandClass BandclassCDMA2000, + cellReselectionPriority CellReselectionPriority +} + +BandClassPriorityList1XRTT ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassPriority1XRTT + +BandClassPriority1XRTT ::= SEQUENCE { + bandClass BandclassCDMA2000, + cellReselectionPriority CellReselectionPriority +} + +CellInfoListGERAN-r9 ::= SEQUENCE (SIZE (1..maxCellInfoGERAN-r9)) OF CellInfoGERAN-r9 + +CellInfoGERAN-r9 ::= SEQUENCE { + physCellId-r9 PhysCellIdGERAN, + carrierFreq-r9 CarrierFreqGERAN, + systemInformation-r9 SystemInfoListGERAN +} + +CellInfoListUTRA-FDD-r9 ::= SEQUENCE (SIZE (1..maxCellInfoUTRA-r9)) OF CellInfoUTRA-FDD-r9 + +CellInfoUTRA-FDD-r9 ::= SEQUENCE { + physCellId-r9 PhysCellIdUTRA-FDD, + utra-BCCH-Container-r9 OCTET STRING +} + +CellInfoListUTRA-TDD-r9 ::= SEQUENCE (SIZE (1..maxCellInfoUTRA-r9)) OF CellInfoUTRA-TDD-r9 + +CellInfoUTRA-TDD-r9 ::= SEQUENCE { + physCellId-r9 PhysCellIdUTRA-TDD, + utra-BCCH-Container-r9 OCTET STRING +} + +CellInfoListUTRA-TDD-r10 ::= SEQUENCE (SIZE (1..maxCellInfoUTRA-r9)) OF CellInfoUTRA-TDD-r10 + +CellInfoUTRA-TDD-r10 ::= SEQUENCE { + physCellId-r10 PhysCellIdUTRA-TDD, + carrierFreq-r10 ARFCN-ValueUTRA, + utra-BCCH-Container-r10 OCTET STRING +} + + +RRCConnectionRequest ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionRequest-r8 RRCConnectionRequest-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionRequest-r8-IEs ::= SEQUENCE { + ue-Identity InitialUE-Identity, + establishmentCause EstablishmentCause, + spare BIT STRING (SIZE (1)) +} + +InitialUE-Identity ::= CHOICE { + s-TMSI S-TMSI, + randomValue BIT STRING (SIZE (40)) +} + +EstablishmentCause ::= ENUMERATED { + emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, delayTolerantAccess-v1020, mo-VoiceCall-v1280, spare1} + + +RRCConnectionResume-r13 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionResume-r13 RRCConnectionResume-r13-IEs, + spare3 NULL, + spare2 NULL, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionResume-r13-IEs ::= SEQUENCE { + radioResourceConfigDedicated-r13 RadioResourceConfigDedicated OPTIONAL, -- Need ON + nextHopChainingCount-r13 NextHopChainingCount, + measConfig-r13 MeasConfig OPTIONAL, -- Need ON + antennaInfoDedicatedPCell-r13 AntennaInfoDedicated-v10i0 OPTIONAL, -- Need ON + drb-ContinueROHC-r13 ENUMERATED {true} OPTIONAL, -- Need OP + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionResumeComplete-r13 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcConnectionResumeComplete-r13 RRCConnectionResumeComplete-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionResumeComplete-r13-IEs ::= SEQUENCE { + selectedPLMN-Identity-r13 INTEGER (1..maxPLMN-r11) OPTIONAL, + dedicatedInfoNAS-r13 DedicatedInfoNAS OPTIONAL, + rlf-InfoAvailable-r13 ENUMERATED {true} OPTIONAL, + logMeasAvailable-r13 ENUMERATED {true} OPTIONAL, + connEstFailInfoAvailable-r13 ENUMERATED {true} OPTIONAL, + mobilityState-r13 ENUMERATED {normal, medium, high, spare} OPTIONAL, + mobilityHistoryAvail-r13 ENUMERATED {true} OPTIONAL, + logMeasAvailableMBSFN-r13 ENUMERATED {true} OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionResumeRequest-r13 ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionResumeRequest-r13 RRCConnectionResumeRequest-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionResumeRequest-r13-IEs ::= SEQUENCE { + resumeIdentity-r13 CHOICE { + resumeID-r13 ResumeIdentity-r13, + truncatedResumeID-r13 BIT STRING (SIZE (24)) + }, + shortResumeMAC-I-r13 BIT STRING (SIZE (16)), + resumeCause-r13 ResumeCause, + spare BIT STRING (SIZE (1)) +} + +ResumeCause ::= ENUMERATED { + emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, delayTolerantAccess-v1020, mo-VoiceCall-v1280, spare1} + + + +RRCConnectionSetup ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionSetup-r8 RRCConnectionSetup-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionSetup-r8-IEs ::= SEQUENCE { + radioResourceConfigDedicated RadioResourceConfigDedicated, + nonCriticalExtension RRCConnectionSetup-v8a0-IEs OPTIONAL +} + +RRCConnectionSetup-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionSetupComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + rrcConnectionSetupComplete-r8 RRCConnectionSetupComplete-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionSetupComplete-r8-IEs ::= SEQUENCE { + selectedPLMN-Identity INTEGER (1..maxPLMN-r11), + registeredMME RegisteredMME OPTIONAL, + dedicatedInfoNAS DedicatedInfoNAS, + nonCriticalExtension RRCConnectionSetupComplete-v8a0-IEs OPTIONAL +} + +RRCConnectionSetupComplete-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCConnectionSetupComplete-v1020-IEs OPTIONAL +} + +RRCConnectionSetupComplete-v1020-IEs ::= SEQUENCE { + gummei-Type-r10 ENUMERATED {native, mapped} OPTIONAL, + rlf-InfoAvailable-r10 ENUMERATED {true} OPTIONAL, + logMeasAvailable-r10 ENUMERATED {true} OPTIONAL, + rn-SubframeConfigReq-r10 ENUMERATED {required, notRequired} OPTIONAL, + nonCriticalExtension RRCConnectionSetupComplete-v1130-IEs OPTIONAL +} + +RRCConnectionSetupComplete-v1130-IEs ::= SEQUENCE { + connEstFailInfoAvailable-r11 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionSetupComplete-v1250-IEs OPTIONAL +} + +RRCConnectionSetupComplete-v1250-IEs ::= SEQUENCE { + mobilityState-r12 ENUMERATED {normal, medium, high, spare} OPTIONAL, + mobilityHistoryAvail-r12 ENUMERATED {true} OPTIONAL, + logMeasAvailableMBSFN-r12 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionSetupComplete-v1320-IEs OPTIONAL +} + +RRCConnectionSetupComplete-v1320-IEs ::= SEQUENCE { + ce-ModeB-r13 ENUMERATED {supported} OPTIONAL, + s-TMSI-r13 S-TMSI OPTIONAL, + attachWithoutPDN-Connectivity-r13 ENUMERATED {true} OPTIONAL, + up-CIoT-EPS-Optimisation-r13 ENUMERATED {true} OPTIONAL, + cp-CIoT-EPS-Optimisation-r13 ENUMERATED {true} OPTIONAL, + nonCriticalExtension RRCConnectionSetupComplete-v1330-IEs OPTIONAL +} + +RRCConnectionSetupComplete-v1330-IEs ::= SEQUENCE { + ue-CE-NeedULGaps-r13 ENUMERATED {true} OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RegisteredMME ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, + mmegi BIT STRING (SIZE (16)), + mmec MMEC +} + + +SCGFailureInformation-r12 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + scgFailureInformation-r12 SCGFailureInformation-r12-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformation-r12-IEs ::= SEQUENCE { + failureReportSCG-r12 FailureReportSCG-r12 OPTIONAL, + nonCriticalExtension SCGFailureInformation-v1310-IEs OPTIONAL +} + +SCGFailureInformation-v1310-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG-r12 ::= SEQUENCE { + failureType-r12 ENUMERATED {t313-Expiry, randomAccessProblem, + rlc-MaxNumRetx, scg-ChangeFailure }, + measResultServFreqList-r12 MeasResultServFreqList-r10 OPTIONAL, + measResultNeighCells-r12 MeasResultList2EUTRA-r9 OPTIONAL, + ..., + [[ failureType-v1290 ENUMERATED {maxUL-TimingDiff-v1290} OPTIONAL + ]], + [[ measResultServFreqListExt-r13 MeasResultServFreqListExt-r13 OPTIONAL + ]] +} + + +SCPTMConfiguration-r13 ::= SEQUENCE { + sc-mtch-InfoList-r13 SC-MTCH-InfoList-r13, + scptm-NeighbourCellList-r13 SCPTM-NeighbourCellList-r13 OPTIONAL, -- Need OP + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SCPTMConfiguration-v1340 OPTIONAL +} + +SCPTMConfiguration-v1340 ::= SEQUENCE { + p-b-r13 INTEGER (0..3) OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SecurityModeCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + securityModeCommand-r8 SecurityModeCommand-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeCommand-r8-IEs ::= SEQUENCE { + securityConfigSMC SecurityConfigSMC, + nonCriticalExtension SecurityModeCommand-v8a0-IEs OPTIONAL +} + +SecurityModeCommand-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SecurityConfigSMC ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig, + ... +} + + +SecurityModeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeComplete-r8 SecurityModeComplete-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeComplete-r8-IEs ::= SEQUENCE { + nonCriticalExtension SecurityModeComplete-v8a0-IEs OPTIONAL +} + +SecurityModeComplete-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SecurityModeFailure ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeFailure-r8 SecurityModeFailure-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeFailure-r8-IEs ::= SEQUENCE { + nonCriticalExtension SecurityModeFailure-v8a0-IEs OPTIONAL +} + +SecurityModeFailure-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SidelinkUEInformation-r12 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + sidelinkUEInformation-r12 SidelinkUEInformation-r12-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +SidelinkUEInformation-r12-IEs ::= SEQUENCE { + commRxInterestedFreq-r12 ARFCN-ValueEUTRA-r9 OPTIONAL, + commTxResourceReq-r12 SL-CommTxResourceReq-r12 OPTIONAL, + discRxInterest-r12 ENUMERATED {true} OPTIONAL, + discTxResourceReq-r12 INTEGER (1..63) OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SidelinkUEInformation-v1310-IEs OPTIONAL +} + +SidelinkUEInformation-v1310-IEs ::= SEQUENCE { + commTxResourceReqUC-r13 SL-CommTxResourceReq-r12 OPTIONAL, + commTxResourceInfoReqRelay-r13 SEQUENCE { + commTxResourceReqRelay-r13 SL-CommTxResourceReq-r12 OPTIONAL, + commTxResourceReqRelayUC-r13 SL-CommTxResourceReq-r12 OPTIONAL, + ue-Type-r13 ENUMERATED {relayUE, remoteUE} + } OPTIONAL, + discTxResourceReq-v1310 SEQUENCE { + carrierFreqDiscTx-r13 INTEGER (1..maxFreq) OPTIONAL, + discTxResourceReqAddFreq-r13 SL-DiscTxResourceReqPerFreqList-r13 OPTIONAL + } OPTIONAL, + discTxResourceReqPS-r13 SL-DiscTxResourceReq-r13 OPTIONAL, + discRxGapReq-r13 SL-GapRequest-r13 OPTIONAL, + discTxGapReq-r13 SL-GapRequest-r13 OPTIONAL, + discSysInfoReportFreqList-r13 SL-DiscSysInfoReportFreqList-r13 OPTIONAL, + nonCriticalExtension SidelinkUEInformation-v14x0-IEs OPTIONAL +} + +SidelinkUEInformation-v14x0-IEs ::= SEQUENCE { + v2x-CommRxInterestedFreq-r14 INTEGER (0..maxFreq) OPTIONAL, + v2x-CommTxResourceReq-r14 V2X-CommTxResourceReq-r14 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SL-CommTxResourceReq-r12 ::= SEQUENCE { + carrierFreq-r12 ARFCN-ValueEUTRA-r9 OPTIONAL, + destinationInfoList-r12 SL-DestinationInfoList-r12 +} + +V2X-CommTxResourceReq-r14 ::= SEQUENCE { + v2x-CommTxFreq-r14 INTEGER (0..maxFreq) OPTIONAL, + v2x-DestinationInfoList-r14 SL-DestinationInfoList-r12 OPTIONAL +} + +SL-DiscTxResourceReqPerFreqList-r13 ::= SEQUENCE (SIZE (1..maxFreq)) OF SL-DiscTxResourceReq-r13 + +SL-DiscTxResourceReq-r13 ::= SEQUENCE { + carrierFreqDiscTx-r13 INTEGER (1..maxFreq) OPTIONAL, + discTxResourceReq-r13 INTEGER (1..63) +} + +SL-DestinationInfoList-r12 ::= SEQUENCE (SIZE (1..maxSL-Dest-r12)) OF SL-DestinationIdentity-r12 + +SL-DestinationIdentity-r12 ::= BIT STRING (SIZE (24)) + +SL-DiscSysInfoReportFreqList-r13 ::= SEQUENCE (SIZE (1.. maxSL-DiscSysInfoReportFreq-r13)) OF SL-DiscSysInfoReport-r13 + + +SystemInformation-BR-r13 ::= SystemInformation + +SystemInformation ::= SEQUENCE { + criticalExtensions CHOICE { + systemInformation-r8 SystemInformation-r8-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} +SystemInformation-r8-IEs ::= SEQUENCE { + sib-TypeAndInfo SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + sib2 SystemInformationBlockType2, + sib3 SystemInformationBlockType3, + sib4 SystemInformationBlockType4, + sib5 SystemInformationBlockType5, + sib6 SystemInformationBlockType6, + sib7 SystemInformationBlockType7, + sib8 SystemInformationBlockType8, + sib9 SystemInformationBlockType9, + sib10 SystemInformationBlockType10, + sib11 SystemInformationBlockType11, + ..., + sib12-v920 SystemInformationBlockType12-r9, + sib13-v920 SystemInformationBlockType13-r9, + sib14-v1130 SystemInformationBlockType14-r11, + sib15-v1130 SystemInformationBlockType15-r11, + sib16-v1130 SystemInformationBlockType16-r11, + sib17-v1250 SystemInformationBlockType17-r12, + sib18-v1250 SystemInformationBlockType18-r12, + sib19-v1250 SystemInformationBlockType19-r12, + sib20-v1310 SystemInformationBlockType20-r13, + sib21-v14x0 SystemInformationBlockType21-r14 + }, + nonCriticalExtension SystemInformation-v8a0-IEs OPTIONAL +} + +SystemInformation-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SystemInformationBlockType1-BR-r13 ::= SystemInformationBlockType1 + +SystemInformationBlockType1 ::= SEQUENCE { + cellAccessRelatedInfo SEQUENCE { + plmn-IdentityList PLMN-IdentityList, + trackingAreaCode TrackingAreaCode, + cellIdentity CellIdentity, + cellBarred ENUMERATED {barred, notBarred}, + intraFreqReselection ENUMERATED {allowed, notAllowed}, + csg-Indication BOOLEAN, + csg-Identity CSG-Identity OPTIONAL -- Need OR + }, + cellSelectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinOffset INTEGER (1..8) OPTIONAL -- Need OP + }, + p-Max P-Max OPTIONAL, -- Need OP + freqBandIndicator FreqBandIndicator, + schedulingInfoList SchedulingInfoList, + tdd-Config TDD-Config OPTIONAL, -- Cond TDD + si-WindowLength ENUMERATED { + ms1, ms2, ms5, ms10, ms15, ms20, + ms40}, + systemInfoValueTag INTEGER (0..31), + nonCriticalExtension SystemInformationBlockType1-v890-IEs OPTIONAL +} + +SystemInformationBlockType1-v890-IEs::= SEQUENCE { + lateNonCriticalExtension OCTET STRING (CONTAINING SystemInformationBlockType1-v8h0-IEs) OPTIONAL, + nonCriticalExtension SystemInformationBlockType1-v920-IEs OPTIONAL +} + +-- Late non critical extensions +SystemInformationBlockType1-v8h0-IEs ::= SEQUENCE { + multiBandInfoList MultiBandInfoList OPTIONAL, -- Need OR + nonCriticalExtension SystemInformationBlockType1-v9e0-IEs OPTIONAL +} + +SystemInformationBlockType1-v9e0-IEs ::= SEQUENCE { + freqBandIndicator-v9e0 FreqBandIndicator-v9e0 OPTIONAL, -- Cond FBI-max + multiBandInfoList-v9e0 MultiBandInfoList-v9e0 OPTIONAL, -- Cond mFBI-max + nonCriticalExtension SystemInformationBlockType1-v10j0-IEs OPTIONAL +} + +SystemInformationBlockType1-v10j0-IEs ::= SEQUENCE { + freqBandInfo-r10 NS-PmaxList-r10 OPTIONAL, -- Need OR + multiBandInfoList-v10j0 MultiBandInfoList-v10j0 OPTIONAL, -- Need OR + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non critical extensions +SystemInformationBlockType1-v920-IEs ::= SEQUENCE { + ims-EmergencySupport-r9 ENUMERATED {true} OPTIONAL, -- Need OR + cellSelectionInfo-v920 CellSelectionInfo-v920 OPTIONAL, -- Cond RSRQ + nonCriticalExtension SystemInformationBlockType1-v1130-IEs OPTIONAL +} + +SystemInformationBlockType1-v1130-IEs ::= SEQUENCE { + tdd-Config-v1130 TDD-Config-v1130 OPTIONAL, -- Cond TDD-OR + cellSelectionInfo-v1130 CellSelectionInfo-v1130 OPTIONAL, -- Cond WB-RSRQ + nonCriticalExtension SystemInformationBlockType1-v1250-IEs OPTIONAL +} + +SystemInformationBlockType1-v1250-IEs ::= SEQUENCE { + cellAccessRelatedInfo-v1250 SEQUENCE { + category0Allowed-r12 ENUMERATED {true} OPTIONAL -- Need OP + }, + cellSelectionInfo-v1250 CellSelectionInfo-v1250 OPTIONAL, -- Cond RSRQ2 + freqBandIndicatorPriority-r12 ENUMERATED {true} OPTIONAL, -- Cond mFBI + nonCriticalExtension SystemInformationBlockType1-v1310-IEs OPTIONAL +} + +SystemInformationBlockType1-v1310-IEs ::= SEQUENCE { + hyperSFN-r13 BIT STRING (SIZE (10)) OPTIONAL, -- Need OR + eDRX-Allowed-r13 ENUMERATED {true} OPTIONAL, -- Need OR + cellSelectionInfoCE-r13 CellSelectionInfoCE-r13 OPTIONAL, -- Need OP + bandwidthReducedAccessRelatedInfo-r13 SEQUENCE { + si-WindowLength-BR-r13 ENUMERATED { + ms20, ms40, ms60, ms80, ms120, + ms160, ms200, spare}, + si-RepetitionPattern-r13 ENUMERATED {everyRF, every2ndRF, every4thRF, + every8thRF}, + schedulingInfoList-BR-r13 SchedulingInfoList-BR-r13 OPTIONAL, -- Need OR + fdd-DownlinkOrTddSubframeBitmapBR-r13 CHOICE { + subframePattern10-r13 BIT STRING (SIZE (10)), + subframePattern40-r13 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need OP + fdd-UplinkSubframeBitmapBR-r13 BIT STRING (SIZE (10)) OPTIONAL, -- Need OP + startSymbolBR-r13 INTEGER (1..4), + si-HoppingConfigCommon-r13 ENUMERATED {on,off}, + si-ValidityTime-r13 ENUMERATED {true} OPTIONAL, -- Need OP + systemInfoValueTagList-r13 SystemInfoValueTagList-r13 OPTIONAL -- Need OR + } OPTIONAL, -- Cond BW-reduced + nonCriticalExtension SystemInformationBlockType1-v1320-IEs OPTIONAL +} + +SystemInformationBlockType1-v1320-IEs ::= SEQUENCE { + freqHoppingParametersDL-r13 SEQUENCE { + mpdcch-pdsch-HoppingNB-r13 ENUMERATED {nb2, nb4} OPTIONAL, -- Need OR + interval-DLHoppingConfigCommonModeA-r13 CHOICE { + interval-FDD-r13 ENUMERATED {int1, int2, int4, int8}, + interval-TDD-r13 ENUMERATED {int1, int5, int10, int20} + } OPTIONAL, -- Need OR + interval-DLHoppingConfigCommonModeB-r13 CHOICE { + interval-FDD-r13 ENUMERATED {int2, int4, int8, int16}, + interval-TDD-r13 ENUMERATED { int5, int10, int20, int40} + } OPTIONAL, -- Need OR + mpdcch-pdsch-HoppingOffset-r13 INTEGER (1..maxAvailNarrowBands-r13) OPTIONAL -- Need OR + } OPTIONAL, -- Cond Hopping + nonCriticalExtension SystemInformationBlockType1-v14xy-IEs OPTIONAL +} + +SystemInformationBlockType1-v14xy-IEs ::= SEQUENCE { + eCallOverIMS-Support-r14 ENUMERATED {true} OPTIONAL, -- Need OR + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +PLMN-IdentityList ::= SEQUENCE (SIZE (1..maxPLMN-r11)) OF PLMN-IdentityInfo + +PLMN-IdentityInfo ::= SEQUENCE { + plmn-Identity PLMN-Identity, + cellReservedForOperatorUse ENUMERATED {reserved, notReserved} +} + +SchedulingInfoList ::= SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo + +SchedulingInfo ::= SEQUENCE { + si-Periodicity ENUMERATED { + rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + sib-MappingInfo SIB-MappingInfo +} + +SchedulingInfoList-BR-r13 ::= SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo-BR-r13 + +SchedulingInfo-BR-r13 ::= SEQUENCE { + si-Narrowband-r13 INTEGER (1..maxAvailNarrowBands-r13), + si-TBS-r13 ENUMERATED {b152, b208, b256, b328, b408, b504, b600, b712, + b808, b936} +} + +SIB-MappingInfo ::= SEQUENCE (SIZE (0..maxSIB-1)) OF SIB-Type + +SIB-Type ::= ENUMERATED { + sibType3, sibType4, sibType5, sibType6, + sibType7, sibType8, sibType9, sibType10, + sibType11, sibType12-v920, sibType13-v920, + sibType14-v1130, sibType15-v1130, + sibType16-v1130, sibType17-v1250, sibType18-v1250, + ..., sibType19-v1250, sibType20-v1310, sibType21-v14x0} + +SystemInfoValueTagList-r13 ::= SEQUENCE (SIZE (1..maxSI-Message)) OF SystemInfoValueTagSI-r13 + +SystemInfoValueTagSI-r13 ::= INTEGER (0..3) + +CellSelectionInfo-v920 ::= SEQUENCE { + q-QualMin-r9 Q-QualMin-r9, + q-QualMinOffset-r9 INTEGER (1..8) OPTIONAL -- Need OP +} + +CellSelectionInfo-v1130 ::= SEQUENCE { + q-QualMinWB-r11 Q-QualMin-r9 +} + +CellSelectionInfo-v1250 ::= SEQUENCE { + q-QualMinRSRQ-OnAllSymbols-r12 Q-QualMin-r9 +} + + +UEAssistanceInformation-r11 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ueAssistanceInformation-r11 UEAssistanceInformation-r11-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEAssistanceInformation-r11-IEs ::= SEQUENCE { + powerPrefIndication-r11 ENUMERATED {normal, lowPowerConsumption} OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UECapabilityEnquiry ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + ueCapabilityEnquiry-r8 UECapabilityEnquiry-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquiry-r8-IEs ::= SEQUENCE { + ue-CapabilityRequest UE-CapabilityRequest, + nonCriticalExtension UECapabilityEnquiry-v8a0-IEs OPTIONAL +} + +UECapabilityEnquiry-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UECapabilityEnquiry-v1180-IEs OPTIONAL +} + +UECapabilityEnquiry-v1180-IEs ::= SEQUENCE { + requestedFrequencyBands-r11 SEQUENCE (SIZE (1..16)) OF FreqBandIndicator-r11 OPTIONAL, + nonCriticalExtension UECapabilityEnquiry-v1310-IEs OPTIONAL +} + +UECapabilityEnquiry-v1310-IEs ::= SEQUENCE { + requestReducedFormat-r13 ENUMERATED {true} OPTIONAL, -- Need ON + requestSkipFallbackComb-r13 ENUMERATED {true} OPTIONAL, -- Need ON + requestedMaxCCsDL-r13 INTEGER (2..32) OPTIONAL, -- Need ON + requestedMaxCCsUL-r13 INTEGER (2..32) OPTIONAL, -- Need ON + requestReducedIntNonContComb-r13 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-CapabilityRequest ::= SEQUENCE (SIZE (1..maxRAT-Capabilities)) OF RAT-Type + + +UECapabilityInformation ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + ueCapabilityInformation-r8 UECapabilityInformation-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformation-r8-IEs ::= SEQUENCE { + ue-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList, + nonCriticalExtension UECapabilityInformation-v8a0-IEs OPTIONAL +} + +UECapabilityInformation-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UECapabilityInformation-v1250-IEs OPTIONAL +} + +UECapabilityInformation-v1250-IEs ::= SEQUENCE { + ue-RadioPagingInfo-r12 UE-RadioPagingInfo-r12 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UEInformationRequest-r9 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + ueInformationRequest-r9 UEInformationRequest-r9-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationRequest-r9-IEs ::= SEQUENCE { + rach-ReportReq-r9 BOOLEAN, + rlf-ReportReq-r9 BOOLEAN, + nonCriticalExtension UEInformationRequest-v930-IEs OPTIONAL +} + +UEInformationRequest-v930-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UEInformationRequest-v1020-IEs OPTIONAL +} + +UEInformationRequest-v1020-IEs ::= SEQUENCE { + logMeasReportReq-r10 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension UEInformationRequest-v1130-IEs OPTIONAL +} + +UEInformationRequest-v1130-IEs ::= SEQUENCE { + connEstFailReportReq-r11 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension UEInformationRequest-v1250-IEs OPTIONAL +} + +UEInformationRequest-v1250-IEs ::= SEQUENCE { + mobilityHistoryReportReq-r12 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UEInformationResponse-r9 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + ueInformationResponse-r9 UEInformationResponse-r9-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationResponse-r9-IEs ::= SEQUENCE { + rach-Report-r9 SEQUENCE { + numberOfPreamblesSent-r9 NumberOfPreamblesSent-r11, + contentionDetected-r9 BOOLEAN + } OPTIONAL, + rlf-Report-r9 RLF-Report-r9 OPTIONAL, + nonCriticalExtension UEInformationResponse-v930-IEs OPTIONAL +} + +-- Late non critical extensions +UEInformationResponse-v9e0-IEs ::= SEQUENCE { + rlf-Report-v9e0 RLF-Report-v9e0 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non critical extensions +UEInformationResponse-v930-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING (CONTAINING UEInformationResponse-v9e0-IEs) OPTIONAL, + nonCriticalExtension UEInformationResponse-v1020-IEs OPTIONAL +} + +UEInformationResponse-v1020-IEs ::= SEQUENCE { + logMeasReport-r10 LogMeasReport-r10 OPTIONAL, + nonCriticalExtension UEInformationResponse-v1130-IEs OPTIONAL +} + +UEInformationResponse-v1130-IEs ::= SEQUENCE { + connEstFailReport-r11 ConnEstFailReport-r11 OPTIONAL, + nonCriticalExtension UEInformationResponse-v1250-IEs OPTIONAL +} + +UEInformationResponse-v1250-IEs ::= SEQUENCE { + mobilityHistoryReport-r12 MobilityHistoryReport-r12 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RLF-Report-r9 ::= SEQUENCE { + measResultLastServCell-r9 SEQUENCE { + rsrpResult-r9 RSRP-Range, + rsrqResult-r9 RSRQ-Range OPTIONAL + }, + measResultNeighCells-r9 SEQUENCE { + measResultListEUTRA-r9 MeasResultList2EUTRA-r9 OPTIONAL, + measResultListUTRA-r9 MeasResultList2UTRA-r9 OPTIONAL, + measResultListGERAN-r9 MeasResultListGERAN OPTIONAL, + measResultsCDMA2000-r9 MeasResultList2CDMA2000-r9 OPTIONAL + } OPTIONAL, + ..., + [[ locationInfo-r10 LocationInfo-r10 OPTIONAL, + failedPCellId-r10 CHOICE { + cellGlobalId-r10 CellGlobalIdEUTRA, + pci-arfcn-r10 SEQUENCE { + physCellId-r10 PhysCellId, + carrierFreq-r10 ARFCN-ValueEUTRA + } + } OPTIONAL, + reestablishmentCellId-r10 CellGlobalIdEUTRA OPTIONAL, + timeConnFailure-r10 INTEGER (0..1023) OPTIONAL, + connectionFailureType-r10 ENUMERATED {rlf, hof} OPTIONAL, + previousPCellId-r10 CellGlobalIdEUTRA OPTIONAL + ]], + [[ failedPCellId-v1090 SEQUENCE { + carrierFreq-v1090 ARFCN-ValueEUTRA-v9e0 + } OPTIONAL + ]], + [[ basicFields-r11 SEQUENCE { + c-RNTI-r11 C-RNTI, + rlf-Cause-r11 ENUMERATED { + t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, t312-Expiry-r12}, + timeSinceFailure-r11 TimeSinceFailure-r11 + } OPTIONAL, + previousUTRA-CellId-r11 SEQUENCE { + carrierFreq-r11 ARFCN-ValueUTRA, + physCellId-r11 CHOICE { + fdd-r11 PhysCellIdUTRA-FDD, + tdd-r11 PhysCellIdUTRA-TDD + }, + cellGlobalId-r11 CellGlobalIdUTRA OPTIONAL + } OPTIONAL, + selectedUTRA-CellId-r11 SEQUENCE { + carrierFreq-r11 ARFCN-ValueUTRA, + physCellId-r11 CHOICE { + fdd-r11 PhysCellIdUTRA-FDD, + tdd-r11 PhysCellIdUTRA-TDD + } + } OPTIONAL + ]], + [[ failedPCellId-v1250 SEQUENCE { + tac-FailedPCell-r12 TrackingAreaCode + } OPTIONAL, + measResultLastServCell-v1250 RSRQ-Range-v1250 OPTIONAL, + lastServCellRSRQ-Type-r12 RSRQ-Type-r12 OPTIONAL, + measResultListEUTRA-v1250 MeasResultList2EUTRA-v1250 OPTIONAL + ]], + [[ drb-EstablishedWithQCI-1-r13 ENUMERATED {qci1} OPTIONAL + ]] +} + +RLF-Report-v9e0 ::= SEQUENCE { + measResultListEUTRA-v9e0 MeasResultList2EUTRA-v9e0 +} + +MeasResultList2EUTRA-r9 ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2EUTRA-r9 + +MeasResultList2EUTRA-v9e0 ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2EUTRA-v9e0 + +MeasResultList2EUTRA-v1250 ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2EUTRA-v1250 + +MeasResult2EUTRA-r9 ::= SEQUENCE { + carrierFreq-r9 ARFCN-ValueEUTRA, + measResultList-r9 MeasResultListEUTRA +} + +MeasResult2EUTRA-v9e0 ::= SEQUENCE { + carrierFreq-v9e0 ARFCN-ValueEUTRA-v9e0 OPTIONAL +} + +MeasResult2EUTRA-v1250 ::= SEQUENCE { + rsrq-Type-r12 RSRQ-Type-r12 OPTIONAL +} + +MeasResultList2UTRA-r9 ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2UTRA-r9 + +MeasResult2UTRA-r9 ::= SEQUENCE { + carrierFreq-r9 ARFCN-ValueUTRA, + measResultList-r9 MeasResultListUTRA +} + +MeasResultList2CDMA2000-r9 ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2CDMA2000-r9 + +MeasResult2CDMA2000-r9 ::= SEQUENCE { + carrierFreq-r9 CarrierFreqCDMA2000, + measResultList-r9 MeasResultsCDMA2000 +} + +LogMeasReport-r10 ::= SEQUENCE { + absoluteTimeStamp-r10 AbsoluteTimeInfo-r10, + traceReference-r10 TraceReference-r10, + traceRecordingSessionRef-r10 OCTET STRING (SIZE (2)), + tce-Id-r10 OCTET STRING (SIZE (1)), + logMeasInfoList-r10 LogMeasInfoList-r10, + logMeasAvailable-r10 ENUMERATED {true} OPTIONAL, + ... +} + +LogMeasInfoList-r10 ::= SEQUENCE (SIZE (1..maxLogMeasReport-r10)) OF LogMeasInfo-r10 + +LogMeasInfo-r10 ::= SEQUENCE { + locationInfo-r10 LocationInfo-r10 OPTIONAL, + relativeTimeStamp-r10 INTEGER (0..7200), + servCellIdentity-r10 CellGlobalIdEUTRA, + measResultServCell-r10 SEQUENCE { + rsrpResult-r10 RSRP-Range, + rsrqResult-r10 RSRQ-Range + }, + measResultNeighCells-r10 SEQUENCE { + measResultListEUTRA-r10 MeasResultList2EUTRA-r9 OPTIONAL, + measResultListUTRA-r10 MeasResultList2UTRA-r9 OPTIONAL, + measResultListGERAN-r10 MeasResultList2GERAN-r10 OPTIONAL, + measResultListCDMA2000-r10 MeasResultList2CDMA2000-r9 OPTIONAL + } OPTIONAL, + ..., + [[ measResultListEUTRA-v1090 MeasResultList2EUTRA-v9e0 OPTIONAL + ]], + [[ measResultListMBSFN-r12 MeasResultListMBSFN-r12 OPTIONAL, + measResultServCell-v1250 RSRQ-Range-v1250 OPTIONAL, + servCellRSRQ-Type-r12 RSRQ-Type-r12 OPTIONAL, + measResultListEUTRA-v1250 MeasResultList2EUTRA-v1250 OPTIONAL + ]], + [[ inDeviceCoexDetected-r13 ENUMERATED {true} OPTIONAL + ]] +} + +MeasResultListMBSFN-r12 ::= SEQUENCE (SIZE (1..maxMBSFN-Area)) OF MeasResultMBSFN-r12 + +MeasResultMBSFN-r12 ::= SEQUENCE { + mbsfn-Area-r12 SEQUENCE { + mbsfn-AreaId-r12 MBSFN-AreaId-r12, + carrierFreq-r12 ARFCN-ValueEUTRA-r9 + }, + rsrpResultMBSFN-r12 RSRP-Range, + rsrqResultMBSFN-r12 MBSFN-RSRQ-Range-r12, + signallingBLER-Result-r12 BLER-Result-r12 OPTIONAL, + dataBLER-MCH-ResultList-r12 DataBLER-MCH-ResultList-r12 OPTIONAL, + ... +} + +DataBLER-MCH-ResultList-r12 ::= SEQUENCE (SIZE (1.. maxPMCH-PerMBSFN)) OF DataBLER-MCH-Result-r12 + +DataBLER-MCH-Result-r12 ::= SEQUENCE { + mch-Index-r12 INTEGER (1..maxPMCH-PerMBSFN), + dataBLER-Result-r12 BLER-Result-r12 +} + +BLER-Result-r12 ::= SEQUENCE { + bler-r12 BLER-Range-r12, + blocksReceived-r12 SEQUENCE { + n-r12 BIT STRING (SIZE (3)), + m-r12 BIT STRING (SIZE (8)) + } +} + +BLER-Range-r12 ::= INTEGER(0..31) + +MeasResultList2GERAN-r10 ::= SEQUENCE (SIZE (1..maxCellListGERAN)) OF MeasResultListGERAN + +ConnEstFailReport-r11 ::= SEQUENCE { + failedCellId-r11 CellGlobalIdEUTRA, + locationInfo-r11 LocationInfo-r10 OPTIONAL, + measResultFailedCell-r11 SEQUENCE { + rsrpResult-r11 RSRP-Range, + rsrqResult-r11 RSRQ-Range OPTIONAL + }, + measResultNeighCells-r11 SEQUENCE { + measResultListEUTRA-r11 MeasResultList2EUTRA-r9 OPTIONAL, + measResultListUTRA-r11 MeasResultList2UTRA-r9 OPTIONAL, + measResultListGERAN-r11 MeasResultListGERAN OPTIONAL, + measResultsCDMA2000-r11 MeasResultList2CDMA2000-r9 OPTIONAL + } OPTIONAL, + numberOfPreamblesSent-r11 NumberOfPreamblesSent-r11, + contentionDetected-r11 BOOLEAN, + maxTxPowerReached-r11 BOOLEAN, + timeSinceFailure-r11 TimeSinceFailure-r11, + measResultListEUTRA-v1130 MeasResultList2EUTRA-v9e0 OPTIONAL, + ..., + [[ measResultFailedCell-v1250 RSRQ-Range-v1250 OPTIONAL, + failedCellRSRQ-Type-r12 RSRQ-Type-r12 OPTIONAL, + measResultListEUTRA-v1250 MeasResultList2EUTRA-v1250 OPTIONAL + ]] +} + +NumberOfPreamblesSent-r11::= INTEGER (1..200) + +TimeSinceFailure-r11 ::= INTEGER (0..172800) + +MobilityHistoryReport-r12 ::= VisitedCellInfoList-r12 + + +ULHandoverPreparationTransfer ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulHandoverPreparationTransfer-r8 ULHandoverPreparationTransfer-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULHandoverPreparationTransfer-r8-IEs ::= SEQUENCE { + cdma2000-Type CDMA2000-Type, + meid BIT STRING (SIZE (56)) OPTIONAL, + dedicatedInfo DedicatedInfoCDMA2000, + nonCriticalExtension ULHandoverPreparationTransfer-v8a0-IEs OPTIONAL +} + +ULHandoverPreparationTransfer-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +ULInformationTransfer ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransfer-r8 ULInformationTransfer-r8-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransfer-r8-IEs ::= SEQUENCE { + dedicatedInfoType CHOICE { + dedicatedInfoNAS DedicatedInfoNAS, + dedicatedInfoCDMA2000-1XRTT DedicatedInfoCDMA2000, + dedicatedInfoCDMA2000-HRPD DedicatedInfoCDMA2000 + }, + nonCriticalExtension ULInformationTransfer-v8a0-IEs OPTIONAL +} + +ULInformationTransfer-v8a0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +WLANConnectionStatusReport-r13 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + wlanConnectionStatusReport-r13 WLANConnectionStatusReport-r13-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +WLANConnectionStatusReport-r13-IEs ::= SEQUENCE { + wlan-Status-r13 WLAN-Status-r13, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SystemInformationBlockType2 ::= SEQUENCE { + ac-BarringInfo SEQUENCE { + ac-BarringForEmergency BOOLEAN, + ac-BarringForMO-Signalling AC-BarringConfig OPTIONAL, -- Need OP + ac-BarringForMO-Data AC-BarringConfig OPTIONAL -- Need OP + } OPTIONAL, -- Need OP + radioResourceConfigCommon RadioResourceConfigCommonSIB, + ue-TimersAndConstants UE-TimersAndConstants, + freqInfo SEQUENCE { + ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL, -- Need OP + ul-Bandwidth ENUMERATED {n6, n15, n25, n50, n75, n100} + OPTIONAL, -- Need OP + additionalSpectrumEmission AdditionalSpectrumEmission + }, + mbsfn-SubframeConfigList MBSFN-SubframeConfigList OPTIONAL, -- Need OR + timeAlignmentTimerCommon TimeAlignmentTimer, + ..., + lateNonCriticalExtension OCTET STRING (CONTAINING SystemInformationBlockType2-v8h0-IEs) OPTIONAL, + [[ ssac-BarringForMMTEL-Voice-r9 AC-BarringConfig OPTIONAL, -- Need OP + ssac-BarringForMMTEL-Video-r9 AC-BarringConfig OPTIONAL -- Need OP + ]], + [[ ac-BarringForCSFB-r10 AC-BarringConfig OPTIONAL -- Need OP + ]], + [[ ac-BarringSkipForMMTELVoice-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ac-BarringSkipForMMTELVideo-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ac-BarringSkipForSMS-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ac-BarringPerPLMN-List-r12 AC-BarringPerPLMN-List-r12 OPTIONAL -- Need OP + ]], + [[ voiceServiceCauseIndication-r12 ENUMERATED {true} OPTIONAL -- Need OP + ]], + [[ acdc-BarringForCommon-r13 ACDC-BarringForCommon-r13 OPTIONAL, -- Need OP + acdc-BarringPerPLMN-List-r13 ACDC-BarringPerPLMN-List-r13 OPTIONAL -- Need OP + ]], + [[ + udt-RestrictingForCommon-r13 UDT-Restricting-r13 OPTIONAL, -- Need OR + udt-RestrictingPerPLMN-List-r13 UDT-RestrictingPerPLMN-List-r13 OPTIONAL, -- Need OR + cIoT-EPS-OptimisationInfo-r13 CIOT-EPS-OptimisationInfo-r13 OPTIONAL, -- Need OP + useFullResumeID-r13 ENUMERATED {true} OPTIONAL -- Need OP + ]] + +} + +SystemInformationBlockType2-v8h0-IEs ::= SEQUENCE { + multiBandInfoList SEQUENCE (SIZE (1..maxMultiBands)) OF AdditionalSpectrumEmission OPTIONAL, -- Need OR + nonCriticalExtension SystemInformationBlockType2-v9e0-IEs OPTIONAL +} + +SystemInformationBlockType2-v9e0-IEs ::= SEQUENCE { + ul-CarrierFreq-v9e0 ARFCN-ValueEUTRA-v9e0 OPTIONAL, -- Cond ul-FreqMax + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +AC-BarringConfig ::= SEQUENCE { + ac-BarringFactor ENUMERATED { + p00, p05, p10, p15, p20, p25, p30, p40, + p50, p60, p70, p75, p80, p85, p90, p95}, + ac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512}, + ac-BarringForSpecialAC BIT STRING (SIZE(5)) +} + +MBSFN-SubframeConfigList ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF MBSFN-SubframeConfig + +AC-BarringPerPLMN-List-r12 ::= SEQUENCE (SIZE (1.. maxPLMN-r11)) OF AC-BarringPerPLMN-r12 + +AC-BarringPerPLMN-r12 ::= SEQUENCE { + plmn-IdentityIndex-r12 INTEGER (1..maxPLMN-r11), + ac-BarringInfo-r12 SEQUENCE { + ac-BarringForEmergency-r12 BOOLEAN, + ac-BarringForMO-Signalling-r12 AC-BarringConfig OPTIONAL, -- Need OP + ac-BarringForMO-Data-r12 AC-BarringConfig OPTIONAL -- Need OP + } OPTIONAL, -- Need OP + ac-BarringSkipForMMTELVoice-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ac-BarringSkipForMMTELVideo-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ac-BarringSkipForSMS-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ac-BarringForCSFB-r12 AC-BarringConfig OPTIONAL, -- Need OP + ssac-BarringForMMTEL-Voice-r12 AC-BarringConfig OPTIONAL, -- Need OP + ssac-BarringForMMTEL-Video-r12 AC-BarringConfig OPTIONAL -- Need OP +} + +ACDC-BarringForCommon-r13 ::= SEQUENCE { + acdc-HPLMNonly-r13 BOOLEAN, + barringPerACDC-CategoryList-r13 BarringPerACDC-CategoryList-r13 +} + +ACDC-BarringPerPLMN-List-r13 ::= SEQUENCE (SIZE (1.. maxPLMN-r11)) OF ACDC-BarringPerPLMN-r13 + +ACDC-BarringPerPLMN-r13 ::= SEQUENCE { + plmn-IdentityIndex-r13 INTEGER (1..maxPLMN-r11), + acdc-OnlyForHPLMN-r13 BOOLEAN, + barringPerACDC-CategoryList-r13 BarringPerACDC-CategoryList-r13 +} + +BarringPerACDC-CategoryList-r13 ::= SEQUENCE (SIZE (1..maxACDC-Cat-r13)) OF BarringPerACDC-Category-r13 + +BarringPerACDC-Category-r13 ::= SEQUENCE { + acdc-Category-r13 INTEGER (1..maxACDC-Cat-r13), + acdc-BarringConfig-r13 SEQUENCE { + ac-BarringFactor-r13 ENUMERATED { + p00, p05, p10, p15, p20, p25, p30, p40, + p50, p60, p70, p75, p80, p85, p90, p95}, + ac-BarringTime-r13 ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512} + } OPTIONAL -- Need OP +} + +UDT-Restricting-r13 ::= SEQUENCE { + udt-Restricting-r13 ENUMERATED {true} OPTIONAL, --Need OR + udt-RestrictingTime-r13 ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512} OPTIONAL --Need OR +} + +UDT-RestrictingPerPLMN-List-r13 ::= SEQUENCE (SIZE (1..maxPLMN-r11)) OF UDT-RestrictingPerPLMN-r13 + +UDT-RestrictingPerPLMN-r13 ::= SEQUENCE { + plmn-IdentityIndex-r13 INTEGER (1..maxPLMN-r11), + udt-Restricting-r13 UDT-Restricting-r13 OPTIONAL --Need OR +} + +CIOT-EPS-OptimisationInfo-r13 ::= SEQUENCE (SIZE (1.. maxPLMN-r11)) OF CIOT-OptimisationPLMN-r13 + +CIOT-OptimisationPLMN-r13::= SEQUENCE { + up-CIoT-EPS-Optimisation-r13 ENUMERATED {true} OPTIONAL, -- Need OP + cp-CIoT-EPS-Optimisation-r13 ENUMERATED {true} OPTIONAL, -- Need OP + attachWithoutPDN-Connectivity-r13 ENUMERATED {true} OPTIONAL -- Need OP +} + + +SystemInformationBlockType3 ::= SEQUENCE { + cellReselectionInfoCommon SEQUENCE { + q-Hyst ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24}, + speedStateReselectionPars SEQUENCE { + mobilityStateParameters MobilityStateParameters, + q-HystSF SEQUENCE { + sf-Medium ENUMERATED { + dB-6, dB-4, dB-2, dB0}, + sf-High ENUMERATED { + dB-6, dB-4, dB-2, dB0} + } + } OPTIONAL -- Need OP + }, + cellReselectionServingFreqInfo SEQUENCE { + s-NonIntraSearch ReselectionThreshold OPTIONAL, -- Need OP + threshServingLow ReselectionThreshold, + cellReselectionPriority CellReselectionPriority + }, + intraFreqCellReselectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + p-Max P-Max OPTIONAL, -- Need OP + s-IntraSearch ReselectionThreshold OPTIONAL, -- Need OP + allowedMeasBandwidth AllowedMeasBandwidth OPTIONAL, -- Need OP + presenceAntennaPort1 PresenceAntennaPort1, + neighCellConfig NeighCellConfig, + t-ReselectionEUTRA T-Reselection, + t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL -- Need OP + }, + ..., + lateNonCriticalExtension OCTET STRING (CONTAINING SystemInformationBlockType3-v10j0-IEs) OPTIONAL, + [[ s-IntraSearch-v920 SEQUENCE { + s-IntraSearchP-r9 ReselectionThreshold, + s-IntraSearchQ-r9 ReselectionThresholdQ-r9 + } OPTIONAL, -- Need OP + s-NonIntraSearch-v920 SEQUENCE { + s-NonIntraSearchP-r9 ReselectionThreshold, + s-NonIntraSearchQ-r9 ReselectionThresholdQ-r9 + } OPTIONAL, -- Need OP + q-QualMin-r9 Q-QualMin-r9 OPTIONAL, -- Need OP + threshServingLowQ-r9 ReselectionThresholdQ-r9 OPTIONAL -- Need OP + ]], + [[ q-QualMinWB-r11 Q-QualMin-r9 OPTIONAL -- Cond WB-RSRQ + ]], + [[ q-QualMinRSRQ-OnAllSymbols-r12 Q-QualMin-r9 OPTIONAL -- Cond RSRQ + ]], + [[ cellReselectionServingFreqInfo-v1310 CellReselectionServingFreqInfo-v1310 OPTIONAL, -- Need OP + redistributionServingInfo-r13 RedistributionServingInfo-r13 OPTIONAL, --Need OR + cellSelectionInfoCE-r13 CellSelectionInfoCE-r13 OPTIONAL, -- Need OP + t-ReselectionEUTRA-CE-r13 T-ReselectionEUTRA-CE-r13 OPTIONAL -- Need OP + ]] +} + +RedistributionServingInfo-r13 ::= SEQUENCE { + redistributionFactorServing-r13 INTEGER(0..10), + redistributionFactorCell-r13 ENUMERATED{true} OPTIONAL, --Need OP + t360-r13 ENUMERATED {min4, min8, min16, min32,infinity, + spare3,spare2,spare1}, + redistrOnPagingOnly-r13 ENUMERATED {true} OPTIONAL --Need OP +} + +CellReselectionServingFreqInfo-v1310 ::= SEQUENCE { + cellReselectionSubPriority-r13 CellReselectionSubPriority-r13 +} + +-- Late non critical extensions +SystemInformationBlockType3-v10j0-IEs ::= SEQUENCE { + freqBandInfo-r10 NS-PmaxList-r10 OPTIONAL, -- Need OR + multiBandInfoList-v10j0 MultiBandInfoList-v10j0 OPTIONAL, -- Need OR + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SystemInformationBlockType4 ::= SEQUENCE { + intraFreqNeighCellList IntraFreqNeighCellList OPTIONAL, -- Need OR + intraFreqBlackCellList IntraFreqBlackCellList OPTIONAL, -- Need OR + csg-PhysCellIdRange PhysCellIdRange OPTIONAL, -- Cond CSG + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL +} + +IntraFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo + +IntraFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + ... +} + +IntraFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellIdRange + + +SystemInformationBlockType5 ::= SEQUENCE { + interFreqCarrierFreqList InterFreqCarrierFreqList, + ..., + lateNonCriticalExtension OCTET STRING (CONTAINING SystemInformationBlockType5-v8h0-IEs) OPTIONAL, + [[ interFreqCarrierFreqList-v1250 InterFreqCarrierFreqList-v1250 OPTIONAL, -- Need OR + interFreqCarrierFreqListExt-r12 InterFreqCarrierFreqListExt-r12 OPTIONAL -- Need OR + ]], + [[ interFreqCarrierFreqListExt-v1280 InterFreqCarrierFreqListExt-v1280 OPTIONAL -- Need OR + ]], + [[ interFreqCarrierFreqList-v1310 InterFreqCarrierFreqList-v1310 OPTIONAL, -- Need OR + interFreqCarrierFreqListExt-v1310 InterFreqCarrierFreqListExt-v1310 OPTIONAL -- Need OR + ]] +} + +SystemInformationBlockType5-v8h0-IEs ::= SEQUENCE { + interFreqCarrierFreqList-v8h0 SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-v8h0 OPTIONAL, -- Need OP + nonCriticalExtension SystemInformationBlockType5-v9e0-IEs OPTIONAL +} + +SystemInformationBlockType5-v9e0-IEs ::= SEQUENCE { + interFreqCarrierFreqList-v9e0 SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-v9e0 OPTIONAL, -- Need OR + nonCriticalExtension SystemInformationBlockType5-v10j0-IEs OPTIONAL +} + +SystemInformationBlockType5-v10j0-IEs ::= SEQUENCE { + interFreqCarrierFreqList-v10j0 SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-v10j0 OPTIONAL, -- Need OR + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +InterFreqCarrierFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo + +InterFreqCarrierFreqList-v1250 ::= SEQUENCE (SIZE (1.. maxFreq)) OF InterFreqCarrierFreqInfo-v1250 + +InterFreqCarrierFreqListExt-r12 ::= SEQUENCE (SIZE (1.. maxFreq)) OF InterFreqCarrierFreqInfo-r12 + +InterFreqCarrierFreqListExt-v1280 ::= SEQUENCE (SIZE (1.. maxFreq)) OF InterFreqCarrierFreqInfo-v10j0 + +InterFreqCarrierFreqList-v1310 ::= SEQUENCE (SIZE (1.. maxFreq)) OF InterFreqCarrierFreqInfo-v1310 + +InterFreqCarrierFreqListExt-v1310 ::= SEQUENCE (SIZE (1.. maxFreq)) OF InterFreqCarrierFreqInfo-v1310 + +InterFreqCarrierFreqInfo ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueEUTRA, + q-RxLevMin Q-RxLevMin, + p-Max P-Max OPTIONAL, -- Need OP + t-ReselectionEUTRA T-Reselection, + t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need OP + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold, + allowedMeasBandwidth AllowedMeasBandwidth, + presenceAntennaPort1 PresenceAntennaPort1, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP + neighCellConfig NeighCellConfig, + q-OffsetFreq Q-OffsetRange DEFAULT dB0, + interFreqNeighCellList InterFreqNeighCellList OPTIONAL, -- Need OR + interFreqBlackCellList InterFreqBlackCellList OPTIONAL, -- Need OR + ..., + [[ q-QualMin-r9 Q-QualMin-r9 OPTIONAL, -- Need OP + threshX-Q-r9 SEQUENCE { + threshX-HighQ-r9 ReselectionThresholdQ-r9, + threshX-LowQ-r9 ReselectionThresholdQ-r9 + } OPTIONAL -- Cond RSRQ + ]], + [[ q-QualMinWB-r11 Q-QualMin-r9 OPTIONAL -- Cond WB-RSRQ + ]] +} + +InterFreqCarrierFreqInfo-v8h0 ::= SEQUENCE { + multiBandInfoList MultiBandInfoList OPTIONAL -- Need OR +} + +InterFreqCarrierFreqInfo-v9e0 ::= SEQUENCE { + dl-CarrierFreq-v9e0 ARFCN-ValueEUTRA-v9e0 OPTIONAL, -- Cond dl-FreqMax + multiBandInfoList-v9e0 MultiBandInfoList-v9e0 OPTIONAL -- Need OR +} + +InterFreqCarrierFreqInfo-v10j0 ::= SEQUENCE { + freqBandInfo-r10 NS-PmaxList-r10 OPTIONAL, -- Need OR + multiBandInfoList-v10j0 MultiBandInfoList-v10j0 OPTIONAL -- Need OR +} + +InterFreqCarrierFreqInfo-v1250 ::= SEQUENCE { + reducedMeasPerformance-r12 ENUMERATED {true} OPTIONAL, -- Need OP + q-QualMinRSRQ-OnAllSymbols-r12 Q-QualMin-r9 OPTIONAL -- Cond RSRQ2 +} + +InterFreqCarrierFreqInfo-r12 ::= SEQUENCE { + dl-CarrierFreq-r12 ARFCN-ValueEUTRA-r9, + q-RxLevMin-r12 Q-RxLevMin, + p-Max-r12 P-Max OPTIONAL, -- Need OP + t-ReselectionEUTRA-r12 T-Reselection, + t-ReselectionEUTRA-SF-r12 SpeedStateScaleFactors OPTIONAL, -- Need OP + threshX-High-r12 ReselectionThreshold, + threshX-Low-r12 ReselectionThreshold, + allowedMeasBandwidth-r12 AllowedMeasBandwidth, + presenceAntennaPort1-r12 PresenceAntennaPort1, + cellReselectionPriority-r12 CellReselectionPriority OPTIONAL, -- Need OP + neighCellConfig-r12 NeighCellConfig, + q-OffsetFreq-r12 Q-OffsetRange DEFAULT dB0, + interFreqNeighCellList-r12 InterFreqNeighCellList OPTIONAL, -- Need OR + interFreqBlackCellList-r12 InterFreqBlackCellList OPTIONAL, -- Need OR + q-QualMin-r12 Q-QualMin-r9 OPTIONAL, -- Need OP + threshX-Q-r12 SEQUENCE { + threshX-HighQ-r12 ReselectionThresholdQ-r9, + threshX-LowQ-r12 ReselectionThresholdQ-r9 + } OPTIONAL, -- Cond RSRQ + q-QualMinWB-r12 Q-QualMin-r9 OPTIONAL, -- Cond WB-RSRQ + multiBandInfoList-r12 MultiBandInfoList-r11 OPTIONAL, -- Need OR + reducedMeasPerformance-r12 ENUMERATED {true} OPTIONAL, -- Need OP + q-QualMinRSRQ-OnAllSymbols-r12 Q-QualMin-r9 OPTIONAL, -- Cond RSRQ2 +... +} + +InterFreqCarrierFreqInfo-v1310 ::= SEQUENCE { + cellReselectionSubPriority-r13 CellReselectionSubPriority-r13 OPTIONAL, -- Need OP + redistributionInterFreqInfo-r13 RedistributionInterFreqInfo-r13 OPTIONAL, --Need OP + cellSelectionInfoCE-r13 CellSelectionInfoCE-r13 OPTIONAL, -- Need OP + t-ReselectionEUTRA-CE-r13 T-ReselectionEUTRA-CE-r13 OPTIONAL -- Need OP +} + +InterFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo + +InterFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange +} + +InterFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellIdRange + +RedistributionInterFreqInfo-r13 ::= SEQUENCE { + redistributionFactorFreq-r13 RedistributionFactor-r13 OPTIONAL, --Need OP + redistributionNeighCellList-r13 RedistributionNeighCellList-r13 OPTIONAL --Need OP +} + +RedistributionNeighCellList-r13 ::= SEQUENCE (SIZE (1..maxCellInter)) OF RedistributionNeighCell-r13 + +RedistributionNeighCell-r13 ::= SEQUENCE { + physCellId-r13 PhysCellId, + redistributionFactorCell-r13 RedistributionFactor-r13 +} + +RedistributionFactor-r13 ::= INTEGER(1..10) + + +SystemInformationBlockType6 ::= SEQUENCE { + carrierFreqListUTRA-FDD CarrierFreqListUTRA-FDD OPTIONAL, -- Need OR + carrierFreqListUTRA-TDD CarrierFreqListUTRA-TDD OPTIONAL, -- Need OR + t-ReselectionUTRA T-Reselection, + t-ReselectionUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need OP + ..., + lateNonCriticalExtension OCTET STRING (CONTAINING SystemInformationBlockType6-v8h0-IEs) OPTIONAL, + [[ carrierFreqListUTRA-FDD-v1250 SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF + CarrierFreqInfoUTRA-v1250 OPTIONAL, -- Cond UTRA-FDD + carrierFreqListUTRA-TDD-v1250 SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF + CarrierFreqInfoUTRA-v1250 OPTIONAL, -- Cond UTRA-TDD + carrierFreqListUTRA-FDD-Ext-r12 CarrierFreqListUTRA-FDD-Ext-r12 OPTIONAL, -- Cond UTRA-FDD + carrierFreqListUTRA-TDD-Ext-r12 CarrierFreqListUTRA-TDD-Ext-r12 OPTIONAL -- Cond UTRA-TDD + ]] +} + +SystemInformationBlockType6-v8h0-IEs ::= SEQUENCE { + carrierFreqListUTRA-FDD-v8h0 SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF CarrierFreqInfoUTRA-FDD-v8h0 OPTIONAL, -- Cond UTRA-FDD + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +CarrierFreqInfoUTRA-v1250 ::= SEQUENCE { + reducedMeasPerformance-r12 ENUMERATED {true} OPTIONAL -- Need OP +} + +CarrierFreqListUTRA-FDD ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF CarrierFreqUTRA-FDD + +CarrierFreqUTRA-FDD ::= SEQUENCE { + carrierFreq ARFCN-ValueUTRA, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold, + q-RxLevMin INTEGER (-60..-13), + p-MaxUTRA INTEGER (-50..33), + q-QualMin INTEGER (-24..0), + ..., + [[ threshX-Q-r9 SEQUENCE { + threshX-HighQ-r9 ReselectionThresholdQ-r9, + threshX-LowQ-r9 ReselectionThresholdQ-r9 + } OPTIONAL -- Cond RSRQ + ]] +} + +CarrierFreqInfoUTRA-FDD-v8h0 ::= SEQUENCE { + multiBandInfoList SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicator-UTRA-FDD OPTIONAL -- Need OR +} + +CarrierFreqListUTRA-FDD-Ext-r12 ::= SEQUENCE (SIZE (1..maxUTRA-FDD-Carrier)) OF + CarrierFreqUTRA-FDD-Ext-r12 + +CarrierFreqUTRA-FDD-Ext-r12 ::= SEQUENCE { + carrierFreq-r12 ARFCN-ValueUTRA, + cellReselectionPriority-r12 CellReselectionPriority OPTIONAL, -- Need OP + threshX-High-r12 ReselectionThreshold, + threshX-Low-r12 ReselectionThreshold, + q-RxLevMin-r12 INTEGER (-60..-13), + p-MaxUTRA-r12 INTEGER (-50..33), + q-QualMin-r12 INTEGER (-24..0), + threshX-Q-r12 SEQUENCE { + threshX-HighQ-r12 ReselectionThresholdQ-r9, + threshX-LowQ-r12 ReselectionThresholdQ-r9 + } OPTIONAL, -- Cond RSRQ + multiBandInfoList-r12 SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicator-UTRA-FDD OPTIONAL, -- Need OR + reducedMeasPerformance-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ... +} + +CarrierFreqListUTRA-TDD ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF CarrierFreqUTRA-TDD + +CarrierFreqUTRA-TDD ::= SEQUENCE { + carrierFreq ARFCN-ValueUTRA, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold, + q-RxLevMin INTEGER (-60..-13), + p-MaxUTRA INTEGER (-50..33), + ... +} + +CarrierFreqListUTRA-TDD-Ext-r12 ::= SEQUENCE (SIZE (1..maxUTRA-TDD-Carrier)) OF + CarrierFreqUTRA-TDD-r12 + +CarrierFreqUTRA-TDD-r12 ::= SEQUENCE { + carrierFreq-r12 ARFCN-ValueUTRA, + cellReselectionPriority-r12 CellReselectionPriority OPTIONAL, -- Need OP + threshX-High-r12 ReselectionThreshold, + threshX-Low-r12 ReselectionThreshold, + q-RxLevMin-r12 INTEGER (-60..-13), + p-MaxUTRA-r12 INTEGER (-50..33), + reducedMeasPerformance-r12 ENUMERATED {true} OPTIONAL, -- Need OP + ... +} + +FreqBandIndicator-UTRA-FDD ::= INTEGER (1..86) + + +SystemInformationBlockType7 ::= SEQUENCE { + t-ReselectionGERAN T-Reselection, + t-ReselectionGERAN-SF SpeedStateScaleFactors OPTIONAL, -- Need OR + carrierFreqsInfoList CarrierFreqsInfoListGERAN OPTIONAL, -- Need OR + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL +} + +CarrierFreqsInfoListGERAN ::= SEQUENCE (SIZE (1..maxGNFG)) OF CarrierFreqsInfoGERAN + +CarrierFreqsInfoGERAN ::= SEQUENCE { + carrierFreqs CarrierFreqsGERAN, + commonInfo SEQUENCE { + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP + ncc-Permitted BIT STRING (SIZE (8)), + q-RxLevMin INTEGER (0..45), + p-MaxGERAN INTEGER (0..39) OPTIONAL, -- Need OP + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold + }, + ... +} + + +SystemInformationBlockType8 ::= SEQUENCE { + systemTimeInfo SystemTimeInfoCDMA2000 OPTIONAL, -- Need OR + searchWindowSize INTEGER (0..15) OPTIONAL, -- Need OR + parametersHRPD SEQUENCE { + preRegistrationInfoHRPD PreRegistrationInfoHRPD, + cellReselectionParametersHRPD CellReselectionParametersCDMA2000 OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + parameters1XRTT SEQUENCE { + csfb-RegistrationParam1XRTT CSFB-RegistrationParam1XRTT OPTIONAL, -- Need OP + longCodeState1XRTT BIT STRING (SIZE (42)) OPTIONAL, -- Need OR + cellReselectionParameters1XRTT CellReselectionParametersCDMA2000 OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL, + [[ csfb-SupportForDualRxUEs-r9 BOOLEAN OPTIONAL, -- Need OR + cellReselectionParametersHRPD-v920 CellReselectionParametersCDMA2000-v920 OPTIONAL, -- Cond NCL-HRPD + cellReselectionParameters1XRTT-v920 CellReselectionParametersCDMA2000-v920 OPTIONAL, -- Cond NCL-1XRTT + csfb-RegistrationParam1XRTT-v920 CSFB-RegistrationParam1XRTT-v920 OPTIONAL, -- Cond REG-1XRTT + ac-BarringConfig1XRTT-r9 AC-BarringConfig1XRTT-r9 OPTIONAL -- Cond REG-1XRTT + ]], + [[ csfb-DualRxTxSupport-r10 ENUMERATED {true} OPTIONAL -- Cond REG-1XRTT + ]], + [[ sib8-PerPLMN-List-r11 SIB8-PerPLMN-List-r11 OPTIONAL -- Need OR + ]] +} + +CellReselectionParametersCDMA2000 ::= SEQUENCE { + bandClassList BandClassListCDMA2000, + neighCellList NeighCellListCDMA2000, + t-ReselectionCDMA2000 T-Reselection, + t-ReselectionCDMA2000-SF SpeedStateScaleFactors OPTIONAL -- Need OP +} + +CellReselectionParametersCDMA2000-r11 ::= SEQUENCE { + bandClassList BandClassListCDMA2000, + neighCellList-r11 SEQUENCE (SIZE (1..16)) OF NeighCellCDMA2000-r11, + t-ReselectionCDMA2000 T-Reselection, + t-ReselectionCDMA2000-SF SpeedStateScaleFactors OPTIONAL -- Need OP +} + +CellReselectionParametersCDMA2000-v920 ::= SEQUENCE { + neighCellList-v920 NeighCellListCDMA2000-v920 +} + +NeighCellListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF NeighCellCDMA2000 + +NeighCellCDMA2000 ::= SEQUENCE { + bandClass BandclassCDMA2000, + neighCellsPerFreqList NeighCellsPerBandclassListCDMA2000 +} + +NeighCellCDMA2000-r11 ::= SEQUENCE { + bandClass BandclassCDMA2000, + neighFreqInfoList-r11 SEQUENCE (SIZE (1..16)) OF NeighCellsPerBandclassCDMA2000-r11 +} + +NeighCellsPerBandclassListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF NeighCellsPerBandclassCDMA2000 + +NeighCellsPerBandclassCDMA2000 ::= SEQUENCE { + arfcn ARFCN-ValueCDMA2000, + physCellIdList PhysCellIdListCDMA2000 +} + +NeighCellsPerBandclassCDMA2000-r11 ::= SEQUENCE { + arfcn ARFCN-ValueCDMA2000, + physCellIdList-r11 SEQUENCE (SIZE (1..40)) OF PhysCellIdCDMA2000 +} + +NeighCellListCDMA2000-v920 ::= SEQUENCE (SIZE (1..16)) OF NeighCellCDMA2000-v920 + +NeighCellCDMA2000-v920 ::= SEQUENCE { + neighCellsPerFreqList-v920 NeighCellsPerBandclassListCDMA2000-v920 +} + +NeighCellsPerBandclassListCDMA2000-v920 ::= SEQUENCE (SIZE (1..16)) OF NeighCellsPerBandclassCDMA2000-v920 + +NeighCellsPerBandclassCDMA2000-v920 ::= SEQUENCE { + physCellIdList-v920 PhysCellIdListCDMA2000-v920 +} + +PhysCellIdListCDMA2000 ::= SEQUENCE (SIZE (1..16)) OF PhysCellIdCDMA2000 + +PhysCellIdListCDMA2000-v920 ::= SEQUENCE (SIZE (0..24)) OF PhysCellIdCDMA2000 + +BandClassListCDMA2000 ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandClassInfoCDMA2000 + +BandClassInfoCDMA2000 ::= SEQUENCE { + bandClass BandclassCDMA2000, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need OP + threshX-High INTEGER (0..63), + threshX-Low INTEGER (0..63), + ... +} + +AC-BarringConfig1XRTT-r9 ::= SEQUENCE { + ac-Barring0to9-r9 INTEGER (0..63), + ac-Barring10-r9 INTEGER (0..7), + ac-Barring11-r9 INTEGER (0..7), + ac-Barring12-r9 INTEGER (0..7), + ac-Barring13-r9 INTEGER (0..7), + ac-Barring14-r9 INTEGER (0..7), + ac-Barring15-r9 INTEGER (0..7), + ac-BarringMsg-r9 INTEGER (0..7), + ac-BarringReg-r9 INTEGER (0..7), + ac-BarringEmg-r9 INTEGER (0..7) +} + +SIB8-PerPLMN-List-r11 ::= SEQUENCE (SIZE (1..maxPLMN-r11)) OF SIB8-PerPLMN-r11 + +SIB8-PerPLMN-r11 ::= SEQUENCE { + plmn-Identity-r11 INTEGER (1..maxPLMN-r11), + parametersCDMA2000-r11 CHOICE { + explicitValue ParametersCDMA2000-r11, + defaultValue NULL + } +} + +ParametersCDMA2000-r11 ::= SEQUENCE { + systemTimeInfo-r11 CHOICE { + explicitValue SystemTimeInfoCDMA2000, + defaultValue NULL + } OPTIONAL, -- Need OR + searchWindowSize-r11 INTEGER (0..15), + parametersHRPD-r11 SEQUENCE { + preRegistrationInfoHRPD-r11 PreRegistrationInfoHRPD, + cellReselectionParametersHRPD-r11 CellReselectionParametersCDMA2000-r11 OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + parameters1XRTT-r11 SEQUENCE { + csfb-RegistrationParam1XRTT-r11 CSFB-RegistrationParam1XRTT OPTIONAL, -- Need OP + csfb-RegistrationParam1XRTT-Ext-r11 CSFB-RegistrationParam1XRTT-v920 OPTIONAL, -- Cond REG-1XRTT-PerPLMN + longCodeState1XRTT-r11 BIT STRING (SIZE (42)) OPTIONAL, -- Cond PerPLMN-LC + cellReselectionParameters1XRTT-r11 CellReselectionParametersCDMA2000-r11 OPTIONAL, -- Need OR + ac-BarringConfig1XRTT-r11 AC-BarringConfig1XRTT-r9 OPTIONAL, -- Cond REG-1XRTT-PerPLMN + csfb-SupportForDualRxUEs-r11 BOOLEAN OPTIONAL, -- Need OR + csfb-DualRxTxSupport-r11 ENUMERATED {true} OPTIONAL -- Cond REG-1XRTT-PerPLMN + } OPTIONAL, -- Need OR + ... +} + + +SystemInformationBlockType9 ::= SEQUENCE { + hnb-Name OCTET STRING (SIZE(1..48)) OPTIONAL, -- Need OR + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL +} + + +SystemInformationBlockType10 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningType OCTET STRING (SIZE (2)), + dummy OCTET STRING (SIZE (50)) OPTIONAL, -- Need OP + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL +} + + +SystemInformationBlockType11 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL +} + + +SystemInformationBlockType12-r9 ::= SEQUENCE { + messageIdentifier-r9 BIT STRING (SIZE (16)), + serialNumber-r9 BIT STRING (SIZE (16)), + warningMessageSegmentType-r9 ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber-r9 INTEGER (0..63), + warningMessageSegment-r9 OCTET STRING, + dataCodingScheme-r9 OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +SystemInformationBlockType13-r9 ::= SEQUENCE { + mbsfn-AreaInfoList-r9 MBSFN-AreaInfoList-r9, + notificationConfig-r9 MBMS-NotificationConfig-r9, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +SystemInformationBlockType14-r11 ::= SEQUENCE { + eab-Param-r11 CHOICE { + eab-Common-r11 EAB-Config-r11, + eab-PerPLMN-List-r11 SEQUENCE (SIZE (1..maxPLMN-r11)) OF EAB-ConfigPLMN-r11 + } OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +EAB-ConfigPLMN-r11 ::= SEQUENCE { + eab-Config-r11 EAB-Config-r11 OPTIONAL -- Need OR +} + +EAB-Config-r11 ::= SEQUENCE { + eab-Category-r11 ENUMERATED {a, b, c}, + eab-BarringBitmap-r11 BIT STRING (SIZE (10)) +} + + +SystemInformationBlockType15-r11 ::= SEQUENCE { + mbms-SAI-IntraFreq-r11 MBMS-SAI-List-r11 OPTIONAL, -- Need OR + mbms-SAI-InterFreqList-r11 MBMS-SAI-InterFreqList-r11 OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ mbms-SAI-InterFreqList-v1140 MBMS-SAI-InterFreqList-v1140 OPTIONAL -- Cond InterFreq + ]] +} + +MBMS-SAI-List-r11 ::= SEQUENCE (SIZE (1..maxSAI-MBMS-r11)) OF MBMS-SAI-r11 + +MBMS-SAI-r11 ::= INTEGER (0..65535) + +MBMS-SAI-InterFreqList-r11 ::= SEQUENCE (SIZE (1..maxFreq)) OF MBMS-SAI-InterFreq-r11 + +MBMS-SAI-InterFreqList-v1140 ::= SEQUENCE (SIZE (1..maxFreq)) OF MBMS-SAI-InterFreq-v1140 + +MBMS-SAI-InterFreq-r11 ::= SEQUENCE { + dl-CarrierFreq-r11 ARFCN-ValueEUTRA-r9, + mbms-SAI-List-r11 MBMS-SAI-List-r11 +} + +MBMS-SAI-InterFreq-v1140 ::= SEQUENCE { + multiBandInfoList-r11 MultiBandInfoList-r11 OPTIONAL -- Need OR +} + + + +SystemInformationBlockType16-r11 ::= SEQUENCE { + timeInfo-r11 SEQUENCE { + timeInfoUTC-r11 INTEGER (0..549755813887), + dayLightSavingTime-r11 BIT STRING (SIZE (2)) OPTIONAL, -- Need OR + leapSeconds-r11 INTEGER (-127..128) OPTIONAL, -- Need OR + localTimeOffset-r11 INTEGER (-63..64) OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +SystemInformationBlockType17-r12 ::= SEQUENCE { + wlan-OffloadInfoPerPLMN-List-r12 SEQUENCE (SIZE (1..maxPLMN-r11)) OF + WLAN-OffloadInfoPerPLMN-r12 OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +WLAN-OffloadInfoPerPLMN-r12 ::= SEQUENCE { + wlan-OffloadConfigCommon-r12 WLAN-OffloadConfig-r12 OPTIONAL, -- Need OR + wlan-Id-List-r12 WLAN-Id-List-r12 OPTIONAL, -- Need OR + ... +} + +WLAN-Id-List-r12 ::= SEQUENCE (SIZE (1..maxWLAN-Id-r12)) OF WLAN-Identifiers-r12 + +WLAN-Identifiers-r12 ::= SEQUENCE { + ssid-r12 OCTET STRING (SIZE (1..32)) OPTIONAL, -- Need OR + bssid-r12 OCTET STRING (SIZE (6)) OPTIONAL, -- Need OR + hessid-r12 OCTET STRING (SIZE (6)) OPTIONAL, -- Need OR + ... +} + + +SystemInformationBlockType18-r12 ::= SEQUENCE { + commConfig-r12 SEQUENCE { + commRxPool-r12 SL-CommRxPoolList-r12, + commTxPoolNormalCommon-r12 SL-CommTxPoolList-r12 OPTIONAL, -- Need OR + commTxPoolExceptional-r12 SL-CommTxPoolList-r12 OPTIONAL, -- Need OR + commSyncConfig-r12 SL-SyncConfigList-r12 OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ commTxPoolNormalCommonExt-r13 SL-CommTxPoolListExt-r13 OPTIONAL, -- Need OR + commTxResourceUC-ReqAllowed-r13 ENUMERATED {true} OPTIONAL, -- Need OR + commTxAllowRelayCommon-r13 ENUMERATED {true} OPTIONAL -- Need OR + ]] +} + + +SystemInformationBlockType19-r12 ::= SEQUENCE { + discConfig-r12 SEQUENCE { + discRxPool-r12 SL-DiscRxPoolList-r12, + discTxPoolCommon-r12 SL-DiscTxPoolList-r12 OPTIONAL, -- Need OR + discTxPowerInfo-r12 SL-DiscTxPowerInfoList-r12 OPTIONAL, -- Cond Tx + discSyncConfig-r12 SL-SyncConfigList-r12 OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + discInterFreqList-r12 SL-CarrierFreqInfoList-r12 OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ discConfig-v1310 SEQUENCE { + discInterFreqList-v1310 SL-CarrierFreqInfoList-v1310 OPTIONAL, -- Need OR + gapRequestsAllowedCommon ENUMERATED {true} OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + discConfigRelay-r13 SEQUENCE { + relayUE-Config-r13 SL-DiscConfigRelayUE-r13, + remoteUE-Config-r13 SL-DiscConfigRemoteUE-r13 + } OPTIONAL, -- Need OR + discConfigPS-13 SEQUENCE { + discRxPoolPS-r13 SL-DiscRxPoolList-r12, + discTxPoolPS-Common-r13 SL-DiscTxPoolList-r12 OPTIONAL -- Need OR + } OPTIONAL -- Need OR + ]] +} + +SL-CarrierFreqInfoList-r12 ::= SEQUENCE (SIZE (1..maxFreq)) OF SL-CarrierFreqInfo-r12 + +SL-CarrierFreqInfoList-v1310 ::= SEQUENCE (SIZE (1..maxFreq)) OF SL-CarrierFreqInfo-v1310 + +SL-CarrierFreqInfo-r12::= SEQUENCE { + carrierFreq-r12 ARFCN-ValueEUTRA-r9, + plmn-IdentityList-r12 PLMN-IdentityList4-r12 OPTIONAL -- Need OP +} + +SL-DiscConfigRelayUE-r13 ::= SEQUENCE { + threshHigh-r13 RSRP-RangeSL4-r13 OPTIONAL, -- Need OR + threshLow-r13 RSRP-RangeSL4-r13 OPTIONAL, -- Need OR + hystMax-r13 ENUMERATED {dB0, dB3, dB6, dB9, dB12, dBinf} OPTIONAL, -- Cond ThreshHigh + hystMin-r13 ENUMERATED {dB0, dB3, dB6, dB9, dB12} OPTIONAL -- Cond ThreshLow +} + +SL-DiscConfigRemoteUE-r13 ::= SEQUENCE { + threshHigh-r13 RSRP-RangeSL4-r13 OPTIONAL, -- Need OR + hystMax-r13 ENUMERATED {dB0, dB3, dB6, dB9, dB12} OPTIONAL, -- Cond ThreshHigh + reselectionInfoIC-r13 ReselectionInfoRelay-r13 +} + +ReselectionInfoRelay-r13 ::= SEQUENCE { + q-RxLevMin-r13 Q-RxLevMin, + -- Note that the mapping of invidual values may be different for PC5, but the granularity/ + -- number of values is same as for Uu + filterCoefficient-r13 FilterCoefficient, + minHyst-r13 ENUMERATED {dB0, dB3, + dB6, dB9, dB12, dBinf} OPTIONAL -- Need OR +} + +SL-CarrierFreqInfo-v1310::= SEQUENCE { + discResourcesNonPS-r13 SL-ResourcesInterFreq-r13 OPTIONAL, -- Need OR + discResourcesPS-r13 SL-ResourcesInterFreq-r13 OPTIONAL, -- Need OR + discConfigOther-r13 SL-DiscConfigOtherInterFreq-r13 OPTIONAL, -- Need OR + ... +} + +PLMN-IdentityList4-r12 ::= SEQUENCE (SIZE (1..maxPLMN-r11)) OF PLMN-IdentityInfo2-r12 + +PLMN-IdentityInfo2-r12 ::= CHOICE { + plmn-Index-r12 INTEGER (1..maxPLMN-r11), + plmnIdentity-r12 PLMN-Identity +} + +SL-DiscTxResourcesInterFreq-r13 ::= CHOICE { + acquireSI-FromCarrier-r13 NULL, + discTxPoolCommon-r13 SL-DiscTxPoolList-r12, + requestDedicated-r13 NULL, + noTxOnCarrier-r13 NULL +} + +SL-DiscConfigOtherInterFreq-r13::= SEQUENCE { + txPowerInfo-r13 SL-DiscTxPowerInfoList-r12 OPTIONAL, -- Cond Tx + refCarrierCommon-r13 ENUMERATED {pCell} OPTIONAL, -- Need OR + discSyncConfig-r13 SL-SyncConfigListNFreq-r13 OPTIONAL, -- Need OR + discCellSelectionInfo-r13 CellSelectionInfoNFreq-r13 OPTIONAL -- Need OR +} + +SL-ResourcesInterFreq-r13 ::= SEQUENCE { + discRxResourcesInterFreq-r13 SL-DiscRxPoolList-r12 OPTIONAL, -- Need OR + discTxResourcesInterFreq-r13 SL-DiscTxResourcesInterFreq-r13 OPTIONAL -- Need OR +} + + +SystemInformationBlockType20-r13 ::= SEQUENCE { + sc-mcch-RepetionPeriod-r13 ENUMERATED {rf2, rf4, rf8, rf16, rf32, rf64, rf128, rf256}, + sc-mcch-Offset-r13 INTEGER (0..10), + sc-mcch-FirstSubframe-r13 INTEGER (0..9), + sc-mcch-duration-r13 INTEGER (2..9) OPTIONAL, + sc-mcch-ModificationPeriod-r13 ENUMERATED {rf2, rf4, rf8, rf16, rf32, rf64, rf128, rf256, + rf512, rf1024, r2048, rf4096, rf8192, rf16384, rf32768, rf65536}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +SystemInformationBlockType21-r14 ::= SEQUENCE { + sl-V2X-ConfigCommon-r14 SL-V2X-ConfigCommon-r14 OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +SL-V2X-ConfigCommon-r14 ::= SEQUENCE { + v2x-CommRxPool-r14 SL-CommRxPoolListV2X-r14 OPTIONAL, -- Need OR + v2x-CommTxPoolNormalCommon-r14 SL-CommTxPoolListV2X-r14 OPTIONAL, -- Need OR + v2x-CommTxPoolExceptional-r14 SL-CommResourcePoolV2X-r14 OPTIONAL, -- Need OR + v2x-SyncConfig-r14 SL-SyncConfigListV2X-r14 OPTIONAL, -- Need OR + v2x-InterFreqInfoList-r14 SL-InterFreqInfoListV2X-r14 OPTIONAL, -- Need OR + v2x-ResourceSelectionConfig-r14 SL-CommTxPoolSensingConfig-r14 OPTIONAL, -- Need OR + zoneConfig-r14 SL-ZoneConfig-r14 OPTIONAL -- Need OR +} + +SL-CommTxPoolSensingConfig-r14 ::= SEQUENCE { + pssch-TxConfigList-r14 SL-PSSCH-TxConfigList-r14, + thresPSSCH-RSRP-List-r14 SL-ThresPSSCH-RSRP-List-r14, + restrictResourceReservationPeriodList-r14 SL-RestrictResourceReservationPeriodList-r14 OPTIONAL, -- Need OR + probResourceKeep-r14 ENUMERATED {v0, v0dot2, v0dot4, v0dot6, v0dot8, + spare3,spare2, spare1} +} + +AntennaInfoCommon ::= SEQUENCE { + antennaPortsCount ENUMERATED {an1, an2, an4, spare1} +} + +AntennaInfoDedicated ::= SEQUENCE { + transmissionMode ENUMERATED { + tm1, tm2, tm3, tm4, tm5, tm6, + tm7, tm8-v920}, + codebookSubsetRestriction CHOICE { + n2TxAntenna-tm3 BIT STRING (SIZE (2)), + n4TxAntenna-tm3 BIT STRING (SIZE (4)), + n2TxAntenna-tm4 BIT STRING (SIZE (6)), + n4TxAntenna-tm4 BIT STRING (SIZE (64)), + n2TxAntenna-tm5 BIT STRING (SIZE (4)), + n4TxAntenna-tm5 BIT STRING (SIZE (16)), + n2TxAntenna-tm6 BIT STRING (SIZE (4)), + n4TxAntenna-tm6 BIT STRING (SIZE (16)) + } OPTIONAL, -- Cond TM + ue-TransmitAntennaSelection CHOICE{ + release NULL, + setup ENUMERATED {closedLoop, openLoop} + } +} + +AntennaInfoDedicated-v920 ::= SEQUENCE { + codebookSubsetRestriction-v920 CHOICE { + n2TxAntenna-tm8-r9 BIT STRING (SIZE (6)), + n4TxAntenna-tm8-r9 BIT STRING (SIZE (32)) + } OPTIONAL -- Cond TM8 +} + +AntennaInfoDedicated-r10 ::= SEQUENCE { + transmissionMode-r10 ENUMERATED { + tm1, tm2, tm3, tm4, tm5, tm6, tm7, tm8-v920, + tm9-v1020, tm10-v1130, spare6, spare5, spare4, + spare3, spare2, spare1}, + codebookSubsetRestriction-r10 BIT STRING OPTIONAL, -- Cond TMX + ue-TransmitAntennaSelection CHOICE{ + release NULL, + setup ENUMERATED {closedLoop, openLoop} + } +} + +AntennaInfoDedicated-v10i0::= SEQUENCE { + maxLayersMIMO-r10 ENUMERATED {twoLayers, fourLayers, eightLayers} OPTIONAL -- Need OR +} + +AntennaInfoDedicated-v1250 ::= SEQUENCE { + alternativeCodebookEnabledFor4TX-r12 BOOLEAN +} + + +AntennaInfoUL-r10 ::= SEQUENCE { + transmissionModeUL-r10 ENUMERATED {tm1, tm2, spare6, spare5, + spare4, spare3, spare2, spare1} OPTIONAL, -- Need OR + fourAntennaPortActivated-r10 ENUMERATED {setup} OPTIONAL -- Need OR +} + + +CQI-ReportConfig ::= SEQUENCE { + cqi-ReportModeAperiodic CQI-ReportModeAperiodic OPTIONAL, -- Need OR + nomPDSCH-RS-EPRE-Offset INTEGER (-1..6), + cqi-ReportPeriodic CQI-ReportPeriodic OPTIONAL -- Need ON +} + +CQI-ReportConfig-v920 ::= SEQUENCE { + cqi-Mask-r9 ENUMERATED {setup} OPTIONAL, -- Cond cqi-Setup + pmi-RI-Report-r9 ENUMERATED {setup} OPTIONAL -- Cond PMIRI +} + +CQI-ReportConfig-r10 ::= SEQUENCE { + cqi-ReportAperiodic-r10 CQI-ReportAperiodic-r10 OPTIONAL, -- Need ON + nomPDSCH-RS-EPRE-Offset INTEGER (-1..6), + cqi-ReportPeriodic-r10 CQI-ReportPeriodic-r10 OPTIONAL, -- Need ON + pmi-RI-Report-r9 ENUMERATED {setup} OPTIONAL, -- Cond PMIRIPCell + csi-SubframePatternConfig-r10 CHOICE { + release NULL, + setup SEQUENCE { + csi-MeasSubframeSet1-r10 MeasSubframePattern-r10, + csi-MeasSubframeSet2-r10 MeasSubframePattern-r10 + } + } OPTIONAL -- Need ON +} + +CQI-ReportConfig-v1130 ::= SEQUENCE { + cqi-ReportPeriodic-v1130 CQI-ReportPeriodic-v1130, + cqi-ReportBoth-r11 CQI-ReportBoth-r11 +} + +CQI-ReportConfig-v1250 ::= SEQUENCE { + csi-SubframePatternConfig-r12 CHOICE { + release NULL, + setup SEQUENCE { + csi-MeasSubframeSets-r12 BIT STRING (SIZE (10)) + } + } OPTIONAL, -- Need ON + cqi-ReportBoth-v1250 CQI-ReportBoth-v1250 OPTIONAL, -- Need ON + cqi-ReportAperiodic-v1250 CQI-ReportAperiodic-v1250 OPTIONAL, -- Need ON + altCQI-Table-r12 ENUMERATED { + allSubframes, csi-SubframeSet1, + csi-SubframeSet2, spare1} OPTIONAL -- Need OP +} + +CQI-ReportConfig-v1310 ::= SEQUENCE { + cqi-ReportBoth-v1310 CQI-ReportBoth-v1310 OPTIONAL, -- Need ON + cqi-ReportAperiodic-v1310 CQI-ReportAperiodic-v1310 OPTIONAL, -- Need ON + cqi-ReportPeriodic-v1310 CQI-ReportPeriodic-v1310 OPTIONAL -- Need ON +} + +CQI-ReportConfig-v1320 ::= SEQUENCE { + cqi-ReportPeriodic-v1320 CQI-ReportPeriodic-v1320 OPTIONAL -- Need ON +} + +CQI-ReportConfigSCell-r10 ::= SEQUENCE { + cqi-ReportModeAperiodic-r10 CQI-ReportModeAperiodic OPTIONAL, -- Need OR + nomPDSCH-RS-EPRE-Offset-r10 INTEGER (-1..6), + cqi-ReportPeriodicSCell-r10 CQI-ReportPeriodic-r10 OPTIONAL, -- Need ON + pmi-RI-Report-r10 ENUMERATED {setup} OPTIONAL -- Cond PMIRISCell +} + +CQI-ReportPeriodic ::= CHOICE { + release NULL, + setup SEQUENCE { + cqi-PUCCH-ResourceIndex INTEGER (0..1185), + cqi-pmi-ConfigIndex INTEGER (0..1023), + cqi-FormatIndicatorPeriodic CHOICE { + widebandCQI NULL, + subbandCQI SEQUENCE { + k INTEGER (1..4) + } + }, + ri-ConfigIndex INTEGER (0..1023) OPTIONAL, -- Need OR + simultaneousAckNackAndCQI BOOLEAN + } +} + +CQI-ReportPeriodic-r10 ::= CHOICE { + release NULL, + setup SEQUENCE { + cqi-PUCCH-ResourceIndex-r10 INTEGER (0..1184), + cqi-PUCCH-ResourceIndexP1-r10 INTEGER (0..1184) OPTIONAL, -- Need OR + cqi-pmi-ConfigIndex INTEGER (0..1023), + cqi-FormatIndicatorPeriodic-r10 CHOICE { + widebandCQI-r10 SEQUENCE { + csi-ReportMode-r10 ENUMERATED {submode1, submode2} OPTIONAL -- Need OR + }, + subbandCQI-r10 SEQUENCE { + k INTEGER (1..4), + periodicityFactor-r10 ENUMERATED {n2, n4} + } + }, + ri-ConfigIndex INTEGER (0..1023) OPTIONAL, -- Need OR + simultaneousAckNackAndCQI BOOLEAN, + cqi-Mask-r9 ENUMERATED {setup} OPTIONAL, -- Need OR + csi-ConfigIndex-r10 CHOICE { + release NULL, + setup SEQUENCE { + cqi-pmi-ConfigIndex2-r10 INTEGER (0..1023), + ri-ConfigIndex2-r10 INTEGER (0..1023) OPTIONAL -- Need OR + } + } OPTIONAL -- Need ON + } +} + + +CQI-ReportPeriodic-v1130 ::= SEQUENCE { + simultaneousAckNackAndCQI-Format3-r11 ENUMERATED {setup} OPTIONAL, -- Need OR + cqi-ReportPeriodicProcExtToReleaseList-r11 CQI-ReportPeriodicProcExtToReleaseList-r11 OPTIONAL, -- Need ON + cqi-ReportPeriodicProcExtToAddModList-r11 CQI-ReportPeriodicProcExtToAddModList-r11 OPTIONAL -- Need ON +} + +CQI-ReportPeriodic-v1310 ::= SEQUENCE { + cri-ReportConfig-r13 CRI-ReportConfig-r13 OPTIONAL, -- Need OR + simultaneousAckNackAndCQI-Format4-Format5-r13 ENUMERATED {setup} OPTIONAL-- Need OR +} + +CQI-ReportPeriodic-v1320 ::= SEQUENCE { + periodicityFactorWB-r13 ENUMERATED {n2, n4} OPTIONAL -- Need OR +} + +CQI-ReportPeriodicProcExtToAddModList-r11 ::= SEQUENCE (SIZE (1..maxCQI-ProcExt-r11)) OF CQI-ReportPeriodicProcExt-r11 + +CQI-ReportPeriodicProcExtToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxCQI-ProcExt-r11)) OF CQI-ReportPeriodicProcExtId-r11 + +CQI-ReportPeriodicProcExt-r11 ::= SEQUENCE { + cqi-ReportPeriodicProcExtId-r11 CQI-ReportPeriodicProcExtId-r11, + cqi-pmi-ConfigIndex-r11 INTEGER (0..1023), + cqi-FormatIndicatorPeriodic-r11 CHOICE { + widebandCQI-r11 SEQUENCE { + csi-ReportMode-r11 ENUMERATED {submode1, submode2} OPTIONAL -- Need OR + }, + subbandCQI-r11 SEQUENCE { + k INTEGER (1..4), + periodicityFactor-r11 ENUMERATED {n2, n4} + } + }, + ri-ConfigIndex-r11 INTEGER (0..1023) OPTIONAL, -- Need OR + csi-ConfigIndex-r11 CHOICE { + release NULL, + setup SEQUENCE { + cqi-pmi-ConfigIndex2-r11 INTEGER (0..1023), + ri-ConfigIndex2-r11 INTEGER (0..1023) OPTIONAL -- Need OR + } + } OPTIONAL, -- Need ON + ..., + [[ cri-ReportConfig-r13 CRI-ReportConfig-r13 OPTIONAL -- Need ON + ]], + [[ periodicityFactorWB-r13 ENUMERATED {n2, n4} OPTIONAL -- Need ON + ]] +} + +CQI-ReportAperiodic-r10 ::= CHOICE { + release NULL, + setup SEQUENCE { + cqi-ReportModeAperiodic-r10 CQI-ReportModeAperiodic, + aperiodicCSI-Trigger-r10 SEQUENCE { + trigger1-r10 BIT STRING (SIZE (8)), + trigger2-r10 BIT STRING (SIZE (8)) + } OPTIONAL -- Need OR + } +} + +CQI-ReportAperiodic-v1250 ::= CHOICE { + release NULL, + setup SEQUENCE { + aperiodicCSI-Trigger-v1250 SEQUENCE { + trigger-SubframeSetIndicator-r12 ENUMERATED {s1, s2}, + trigger1-SubframeSetIndicator-r12 BIT STRING (SIZE (8)), + trigger2-SubframeSetIndicator-r12 BIT STRING (SIZE (8)) + } + } +} + +CQI-ReportAperiodic-v1310 ::= CHOICE { + release NULL, + setup SEQUENCE { + aperiodicCSI-Trigger-v1310 SEQUENCE { + trigger1-r13 BIT STRING (SIZE (32)), + trigger2-r13 BIT STRING (SIZE (32)), + trigger3-r13 BIT STRING (SIZE (32)), + trigger4-r13 BIT STRING (SIZE (32)), + trigger5-r13 BIT STRING (SIZE (32)), + trigger6-r13 BIT STRING (SIZE (32)) + } OPTIONAL, -- Need ON + aperiodicCSI-Trigger2-r13 CHOICE { + release NULL, + setup SEQUENCE { + trigger1-SubframeSetIndicator-r13 BIT STRING (SIZE (32)), + trigger2-SubframeSetIndicator-r13 BIT STRING (SIZE (32)), + trigger3-SubframeSetIndicator-r13 BIT STRING (SIZE (32)), + trigger4-SubframeSetIndicator-r13 BIT STRING (SIZE (32)), + trigger5-SubframeSetIndicator-r13 BIT STRING (SIZE (32)), + trigger6-SubframeSetIndicator-r13 BIT STRING (SIZE (32)) + } + } OPTIONAL -- Need ON + } +} + +CQI-ReportAperiodicProc-r11 ::= SEQUENCE { + cqi-ReportModeAperiodic-r11 CQI-ReportModeAperiodic, + trigger01-r11 BOOLEAN, + trigger10-r11 BOOLEAN, + trigger11-r11 BOOLEAN +} + +CQI-ReportAperiodicProc-v1310 ::= SEQUENCE { + trigger001-r13 BOOLEAN, + trigger010-r13 BOOLEAN, + trigger011-r13 BOOLEAN, + trigger100-r13 BOOLEAN, + trigger101-r13 BOOLEAN, + trigger110-r13 BOOLEAN, + trigger111-r13 BOOLEAN +} + +CQI-ReportModeAperiodic ::= ENUMERATED { + rm12, rm20, rm22, rm30, rm31, + rm32-v1250, rm10-v1310, rm11-v1310 +} + +CQI-ReportBoth-r11 ::= SEQUENCE { + csi-IM-ConfigToReleaseList-r11 CSI-IM-ConfigToReleaseList-r11 OPTIONAL, -- Need ON + csi-IM-ConfigToAddModList-r11 CSI-IM-ConfigToAddModList-r11 OPTIONAL, -- Need ON + csi-ProcessToReleaseList-r11 CSI-ProcessToReleaseList-r11 OPTIONAL, -- Need ON + csi-ProcessToAddModList-r11 CSI-ProcessToAddModList-r11 OPTIONAL -- Need ON +} + +CQI-ReportBoth-v1250 ::= SEQUENCE { + csi-IM-ConfigToReleaseListExt-r12 CSI-IM-ConfigId-v1250 OPTIONAL, -- Need ON + csi-IM-ConfigToAddModListExt-r12 CSI-IM-ConfigExt-r12 OPTIONAL -- Need ON +} + +CQI-ReportBoth-v1310 ::= SEQUENCE { + csi-IM-ConfigToReleaseListExt-r13 CSI-IM-ConfigToReleaseListExt-r13 OPTIONAL, -- Need ON + csi-IM-ConfigToAddModListExt-r13 CSI-IM-ConfigToAddModListExt-r13 OPTIONAL -- Need ON +} + +CSI-IM-ConfigToAddModList-r11 ::= SEQUENCE (SIZE (1..maxCSI-IM-r11)) OF CSI-IM-Config-r11 + +CSI-IM-ConfigToAddModListExt-r13 ::= SEQUENCE (SIZE (1..maxCSI-IM-v1310)) OF CSI-IM-ConfigExt-r12 + +CSI-IM-ConfigToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxCSI-IM-r11)) OF CSI-IM-ConfigId-r11 + +CSI-IM-ConfigToReleaseListExt-r13 ::= SEQUENCE (SIZE (1..maxCSI-IM-v1310)) OF CSI-IM-ConfigId-v1310 + +CSI-ProcessToAddModList-r11 ::= SEQUENCE (SIZE (1..maxCSI-Proc-r11)) OF CSI-Process-r11 + +CSI-ProcessToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxCSI-Proc-r11)) OF CSI-ProcessId-r11 + +CQI-ReportBothProc-r11 ::= SEQUENCE { + ri-Ref-CSI-ProcessId-r11 CSI-ProcessId-r11 OPTIONAL, -- Need OR + pmi-RI-Report-r11 ENUMERATED {setup} OPTIONAL -- Need OR +} + +CRI-ReportConfig-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + cri-ConfigIndex-r13 CRI-ConfigIndex-r13, + cri-ConfigIndex2-r13 CRI-ConfigIndex-r13 OPTIONAL -- Need OR + } +} + +CRI-ConfigIndex-r13 ::= INTEGER (0..1023) + + +CQI-ReportPeriodicProcExtId-r11 ::= INTEGER (1..maxCQI-ProcExt-r11) + + +CrossCarrierSchedulingConfig-r10 ::= SEQUENCE { + schedulingCellInfo-r10 CHOICE { + own-r10 SEQUENCE { -- No cross carrier scheduling + cif-Presence-r10 BOOLEAN + }, + other-r10 SEQUENCE { -- Cross carrier scheduling + schedulingCellId-r10 ServCellIndex-r10, + pdsch-Start-r10 INTEGER (1..4) + } + } +} + +CrossCarrierSchedulingConfig-r13 ::= SEQUENCE { + schedulingCellInfo-r13 CHOICE { + own-r13 SEQUENCE { -- No cross carrier scheduling + cif-Presence-r13 BOOLEAN + }, + other-r13 SEQUENCE { -- Cross carrier scheduling + schedulingCellId-r13 ServCellIndex-r13, + pdsch-Start-r13 INTEGER (1..4), + cif-InSchedulingCell-r13 INTEGER (1..7) + } + } +} + +CrossCarrierSchedulingConfigLAA-UL-r14 ::= SEQUENCE { + schedulingCellId-r14 ServCellIndex-r13, + cif-InSchedulingCell-r14 INTEGER (1..7) +} + +CSI-IM-Config-r11 ::= SEQUENCE { + csi-IM-ConfigId-r11 CSI-IM-ConfigId-r11, + resourceConfig-r11 INTEGER (0..31), + subframeConfig-r11 INTEGER (0..154), + ..., + [[ interferenceMeasRestriction-r13 BOOLEAN OPTIONAL -- Need ON + ]] +} + +CSI-IM-ConfigExt-r12 ::= SEQUENCE { + csi-IM-ConfigId-v1250 CSI-IM-ConfigId-v1250, + resourceConfig-r12 INTEGER (0..31), + subframeConfig-r12 INTEGER (0..154), + ..., + [[ interferenceMeasRestriction-r13 BOOLEAN OPTIONAL, -- Need ON + csi-IM-ConfigId-v1310 CSI-IM-ConfigId-v1310 OPTIONAL -- Need ON + ]] +} + + +CSI-IM-ConfigId-r11 ::= INTEGER (1..maxCSI-IM-r11) +CSI-IM-ConfigId-r12 ::= INTEGER (1..maxCSI-IM-r12) +CSI-IM-ConfigId-v1250 ::= INTEGER (maxCSI-IM-r12) +CSI-IM-ConfigId-v1310 ::= INTEGER (minCSI-IM-r13..maxCSI-IM-r13) +CSI-IM-ConfigId-r13 ::= INTEGER (1..maxCSI-IM-r13) + + +CSI-Process-r11 ::= SEQUENCE { + csi-ProcessId-r11 CSI-ProcessId-r11, + csi-RS-ConfigNZPId-r11 CSI-RS-ConfigNZPId-r11, + csi-IM-ConfigId-r11 CSI-IM-ConfigId-r11, + p-C-AndCBSRList-r11 P-C-AndCBSR-Pair-r13a, + cqi-ReportBothProc-r11 CQI-ReportBothProc-r11 OPTIONAL, -- Need OR + cqi-ReportPeriodicProcId-r11 INTEGER (0..maxCQI-ProcExt-r11) OPTIONAL, -- Need OR + cqi-ReportAperiodicProc-r11 CQI-ReportAperiodicProc-r11 OPTIONAL, -- Need OR + ..., + [[ alternativeCodebookEnabledFor4TXProc-r12 ENUMERATED {true} OPTIONAL, -- Need ON + csi-IM-ConfigIdList-r12 CHOICE { + release NULL, + setup SEQUENCE (SIZE (1..2)) OF CSI-IM-ConfigId-r12 + } OPTIONAL, -- Need ON + cqi-ReportAperiodicProc2-r12 CHOICE { + release NULL, + setup CQI-ReportAperiodicProc-r11 + } OPTIONAL -- Need ON + ]], + [[ cqi-ReportAperiodicProc-v1310 CHOICE { + release NULL, + setup CQI-ReportAperiodicProc-v1310 + } OPTIONAL, -- Need ON + cqi-ReportAperiodicProc2-v1310 CHOICE { + release NULL, + setup CQI-ReportAperiodicProc-v1310 + } OPTIONAL, -- Need ON + eMIMO-Type-r13 CSI-RS-ConfigEMIMO-r13 OPTIONAL -- Need ON + ]] +} + + +CSI-ProcessId-r11 ::= INTEGER (1..maxCSI-Proc-r11) + + +CSI-RS-Config-r10 ::= SEQUENCE { + csi-RS-r10 CHOICE { + release NULL, + setup SEQUENCE { + antennaPortsCount-r10 ENUMERATED {an1, an2, an4, an8}, + resourceConfig-r10 INTEGER (0..31), + subframeConfig-r10 INTEGER (0..154), + p-C-r10 INTEGER (-8..15) + } + } OPTIONAL, -- Need ON + zeroTxPowerCSI-RS-r10 ZeroTxPowerCSI-RS-Conf-r12 OPTIONAL -- Need ON +} + +CSI-RS-Config-v1250 ::= SEQUENCE { + zeroTxPowerCSI-RS2-r12 ZeroTxPowerCSI-RS-Conf-r12 OPTIONAL, -- Need ON + ds-ZeroTxPowerCSI-RS-r12 CHOICE { + release NULL, + setup SEQUENCE { + zeroTxPowerCSI-RS-List-r12 SEQUENCE (SIZE (1..maxDS-ZTP-CSI-RS-r12)) OF ZeroTxPowerCSI-RS-r12 + } + } OPTIONAL -- Need ON +} + +CSI-RS-Config-v1310 ::= SEQUENCE { + eMIMO-Type-r13 CSI-RS-ConfigEMIMO-r13 OPTIONAL -- Need ON +} + +ZeroTxPowerCSI-RS-Conf-r12 ::= CHOICE { + release NULL, + setup ZeroTxPowerCSI-RS-r12 +} + +ZeroTxPowerCSI-RS-r12 ::= SEQUENCE { + zeroTxPowerResourceConfigList-r12 BIT STRING (SIZE (16)), + zeroTxPowerSubframeConfig-r12 INTEGER (0..154) +} + + +CSI-RS-ConfigEMIMO-r13 ::= CHOICE { + release NULL, + setup CHOICE { + nonPrecoded-r13 CSI-RS-ConfigNonPrecoded-r13, + beamformed-r13 CSI-RS-ConfigBeamformed-r13 + } +} + +CSI-RS-ConfigNonPrecoded-r13 ::= SEQUENCE { + p-C-AndCBSRList-r13 P-C-AndCBSR-Pair-r13 OPTIONAL, -- Need OR + codebookConfigN1-r13 ENUMERATED {n1, n2, n3, n4, n8}, + codebookConfigN2-r13 ENUMERATED {n1, n2, n3, n4, n8}, + codebookOverSamplingRateConfig-O1-r13 ENUMERATED {n4, n8} OPTIONAL, -- Need OR + codebookOverSamplingRateConfig-O2-r13 ENUMERATED {n4, n8} OPTIONAL, -- Need OR + codebookConfig-r13 INTEGER (1..4), + csi-IM-ConfigIdList-r13 SEQUENCE (SIZE (1..2)) OF CSI-IM-ConfigId-r13 OPTIONAL, -- Need OR + csi-RS-ConfigNZP-EMIMO-r13 CSI-RS-ConfigNZP-EMIMO-r13 OPTIONAL -- Need ON +} + +CSI-RS-ConfigBeamformed-r13 ::= SEQUENCE { + csi-RS-ConfigNZPIdListExt-r13 SEQUENCE (SIZE (1..7)) OF CSI-RS-ConfigNZPId-r13 OPTIONAL, -- Need OR + csi-IM-ConfigIdList-r13 SEQUENCE (SIZE (1..8)) OF CSI-IM-ConfigId-r13 OPTIONAL, -- Need OR + p-C-AndCBSR-PerResourceConfigList-r13 SEQUENCE (SIZE (1..8)) OF P-C-AndCBSR-Pair-r13 OPTIONAL, -- Need OR + ace-For4Tx-PerResourceConfigList-r13 SEQUENCE (SIZE (1..7)) OF BOOLEAN OPTIONAL, -- Need OR + alternativeCodebookEnabledBeamformed-r13 ENUMERATED {true} OPTIONAL, -- Need OR + channelMeasRestriction-r13 ENUMERATED {on} OPTIONAL -- Need OR +} + + +CSI-RS-ConfigNZP-r11 ::= SEQUENCE { + csi-RS-ConfigNZPId-r11 CSI-RS-ConfigNZPId-r11, + antennaPortsCount-r11 ENUMERATED {an1, an2, an4, an8}, + resourceConfig-r11 INTEGER (0..31), + subframeConfig-r11 INTEGER (0..154), + scramblingIdentity-r11 INTEGER (0..503), + qcl-CRS-Info-r11 SEQUENCE { + qcl-ScramblingIdentity-r11 INTEGER (0..503), + crs-PortsCount-r11 ENUMERATED {n1, n2, n4, spare1}, + mbsfn-SubframeConfigList-r11 CHOICE { + release NULL, + setup SEQUENCE { + subframeConfigList MBSFN-SubframeConfigList + } + } OPTIONAL -- Need ON + } OPTIONAL, -- Need OR + ..., + [[ csi-RS-ConfigNZPId-v1310 CSI-RS-ConfigNZPId-v1310 OPTIONAL -- Need ON + ]] +} + +CSI-RS-ConfigNZP-EMIMO-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + nzp-resourceConfigList-r13 SEQUENCE (SIZE (1..2)) OF NZP-ResourceConfig-r13, + cdmType-r13 ENUMERATED {cdm2, cdm4} OPTIONAL -- Need OR + } +} + +NZP-ResourceConfig-r13 ::= SEQUENCE { + resourceConfig-r13 ResourceConfig-r13, + ... +} + +ResourceConfig-r13 ::= INTEGER (0..31) + + +CSI-RS-ConfigNZPId-r11 ::= INTEGER (1..maxCSI-RS-NZP-r11) +CSI-RS-ConfigNZPId-v1310 ::= INTEGER (minCSI-RS-NZP-r13..maxCSI-RS-NZP-r13) +CSI-RS-ConfigNZPId-r13 ::= INTEGER (1..maxCSI-RS-NZP-r13) + + +CSI-RS-ConfigZP-r11 ::= SEQUENCE { + csi-RS-ConfigZPId-r11 CSI-RS-ConfigZPId-r11, + resourceConfigList-r11 BIT STRING (SIZE (16)), + subframeConfig-r11 INTEGER (0..154), + ... +} + + +CSI-RS-ConfigZPId-r11 ::= INTEGER (1..maxCSI-RS-ZP-r11) + + +DMRS-Config-r11 ::= CHOICE { + release NULL, + setup SEQUENCE { + scramblingIdentity-r11 INTEGER (0..503), + scramblingIdentity2-r11 INTEGER (0..503) + } +} +DMRS-Config-v1310 ::= SEQUENCE { + dmrs-tableAlt-r13 ENUMERATED {true} OPTIONAL -- Need OR +} + + +DRB-Identity ::= INTEGER (1..32) + + +EPDCCH-Config-r11 ::= SEQUENCE{ + config-r11 CHOICE { + release NULL, + setup SEQUENCE { + subframePatternConfig-r11 CHOICE { + release NULL, + setup SEQUENCE { + subframePattern-r11 MeasSubframePattern-r10 + } + } OPTIONAL, -- Need ON + startSymbol-r11 INTEGER (1..4) OPTIONAL, -- Need OP + setConfigToReleaseList-r11 EPDCCH-SetConfigToReleaseList-r11 OPTIONAL, -- Need ON + setConfigToAddModList-r11 EPDCCH-SetConfigToAddModList-r11 OPTIONAL -- Need ON + } + } +} + +EPDCCH-SetConfigToAddModList-r11 ::= SEQUENCE (SIZE(1..maxEPDCCH-Set-r11)) OF EPDCCH-SetConfig-r11 + +EPDCCH-SetConfigToReleaseList-r11 ::= SEQUENCE (SIZE(1..maxEPDCCH-Set-r11)) OF EPDCCH-SetConfigId-r11 + +EPDCCH-SetConfig-r11 ::= SEQUENCE { + setConfigId-r11 EPDCCH-SetConfigId-r11, + transmissionType-r11 ENUMERATED {localised, distributed}, + resourceBlockAssignment-r11 SEQUENCE{ + numberPRB-Pairs-r11 ENUMERATED {n2, n4, n8}, + resourceBlockAssignment-r11 BIT STRING (SIZE(4..38)) + }, + dmrs-ScramblingSequenceInt-r11 INTEGER (0..503), + pucch-ResourceStartOffset-r11 INTEGER (0..2047), + re-MappingQCL-ConfigId-r11 PDSCH-RE-MappingQCL-ConfigId-r11 OPTIONAL, -- Need OR + ..., + [[ csi-RS-ConfigZPId2-r12 CHOICE { + release NULL, + setup CSI-RS-ConfigZPId-r11 + } OPTIONAL -- Need ON + ]], + [[ numberPRB-Pairs-v1310 CHOICE { + release NULL, + setup ENUMERATED {n6} + } OPTIONAL, -- Need ON + mpdcch-config-r13 CHOICE { + release NULL, + setup SEQUENCE { + csi-NumRepetitionCE-r13 ENUMERATED {sf1, sf2, sf4, sf8, sf16, sf32}, + mpdcch-pdsch-HoppingConfig-r13 ENUMERATED {on,off}, + mpdcch-StartSF-UESS-r13 CHOICE { + fdd-r13 ENUMERATED {v1, v1dot5, v2, v2dot5, v4, + v5, v8, v10}, tdd-r13 ENUMERATED {v1, v2, v4, v5, v8, v10, + v20, spare1} + }, + mpdcch-NumRepetition-r13 ENUMERATED {r1, r2, r4, r8, r16, + r32, r64, r128, r256}, + mpdcch-Narrowband-r13 INTEGER (1.. maxAvailNarrowBands-r13) + } + } OPTIONAL -- Need ON + ]] +} + +EPDCCH-SetConfigId-r11 ::= INTEGER (0..1) + + +EIMTA-MainConfig-r12 ::= CHOICE { + release NULL, + setup SEQUENCE { + eimta-RNTI-r12 C-RNTI, + eimta-CommandPeriodicity-r12 ENUMERATED {sf10, sf20, sf40, sf80}, + eimta-CommandSubframeSet-r12 BIT STRING (SIZE(10)) + } +} + +EIMTA-MainConfigServCell-r12 ::= CHOICE { + release NULL, + setup SEQUENCE { + eimta-UL-DL-ConfigIndex-r12 INTEGER (1..5), + eimta-HARQ-ReferenceConfig-r12 ENUMERATED {sa2,sa4,sa5}, + mbsfn-SubframeConfigList-v1250 CHOICE { + release NULL, + setup SEQUENCE { + subframeConfigList-r12 MBSFN-SubframeConfigList + } + } + } +} + + +LogicalChannelConfig ::= SEQUENCE { + ul-SpecificParameters SEQUENCE { + priority INTEGER (1..16), + prioritisedBitRate ENUMERATED { + kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, + kBps256, infinity, kBps512-v1020, kBps1024-v1020, + kBps2048-v1020, spare5, spare4, spare3, spare2, + spare1}, + bucketSizeDuration ENUMERATED { + ms50, ms100, ms150, ms300, ms500, ms1000, spare2, + spare1}, + logicalChannelGroup INTEGER (0..3) OPTIONAL -- Need OR + } OPTIONAL, -- Cond UL + ..., + [[ logicalChannelSR-Mask-r9 ENUMERATED {setup} OPTIONAL -- Cond SRmask + ]], + [[ logicalChannelSR-Prohibit-r12 BOOLEAN OPTIONAL -- Need ON + ]], + [[ laa-Allowed-r14 BOOLEAN OPTIONAL -- Need ON + ]] +} + + +LWA-Configuration-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + lwa-Config-r13 LWA-Config-r13 + } +} + +LWA-Config-r13 ::= SEQUENCE { + lwa-MobilityConfig-r13 WLAN-MobilityConfig-r13 OPTIONAL, -- Need ON + lwa-WT-Counter-r13 INTEGER (0..65535) OPTIONAL, -- Need ON + ... +} + + +LWIP-Configuration-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + lwip-Config-r13 LWIP-Config-r13 + } +} + +LWIP-Config-r13 ::= SEQUENCE { + lwip-MobilityConfig-r13 WLAN-MobilityConfig-r13 OPTIONAL, -- Need ON + tunnelConfigLWIP-r13 TunnelConfigLWIP-r13 OPTIONAL, -- Need ON + ... +} + + +MAC-MainConfig ::= SEQUENCE { + ul-SCH-Config SEQUENCE { + maxHARQ-Tx ENUMERATED { + n1, n2, n3, n4, n5, n6, n7, n8, + n10, n12, n16, n20, n24, n28, + spare2, spare1} OPTIONAL, -- Need ON + periodicBSR-Timer PeriodicBSR-Timer-r12 OPTIONAL, -- Need ON + retxBSR-Timer RetxBSR-Timer-r12, + ttiBundling BOOLEAN + } OPTIONAL, -- Need ON + drx-Config DRX-Config OPTIONAL, -- Need ON + timeAlignmentTimerDedicated TimeAlignmentTimer, + phr-Config CHOICE { + release NULL, + setup SEQUENCE { + periodicPHR-Timer ENUMERATED {sf10, sf20, sf50, sf100, sf200, + sf500, sf1000, infinity}, + prohibitPHR-Timer ENUMERATED {sf0, sf10, sf20, sf50, sf100, + sf200, sf500, sf1000}, + dl-PathlossChange ENUMERATED {dB1, dB3, dB6, infinity} + } + } OPTIONAL, -- Need ON + ..., + [[ sr-ProhibitTimer-r9 INTEGER (0..7) OPTIONAL -- Need ON + ]], + [[ mac-MainConfig-v1020 SEQUENCE { + sCellDeactivationTimer-r10 ENUMERATED { + rf2, rf4, rf8, rf16, rf32, rf64, rf128, + spare} OPTIONAL, -- Need OP + extendedBSR-Sizes-r10 ENUMERATED {setup} OPTIONAL, -- Need OR + extendedPHR-r10 ENUMERATED {setup} OPTIONAL -- Need OR + } OPTIONAL -- Need ON + ]], + [[ stag-ToReleaseList-r11 STAG-ToReleaseList-r11 OPTIONAL, -- Need ON + stag-ToAddModList-r11 STAG-ToAddModList-r11 OPTIONAL, -- Need ON + drx-Config-v1130 DRX-Config-v1130 OPTIONAL -- Need ON + ]], + [[ e-HARQ-Pattern-r12 BOOLEAN OPTIONAL, -- Need ON + dualConnectivityPHR CHOICE { + release NULL, + setup SEQUENCE { + phr-ModeOtherCG-r12 ENUMERATED {real, virtual} + } + } OPTIONAL, -- Need ON + logicalChannelSR-Config-r12 CHOICE { + release NULL, + setup SEQUENCE { + logicalChannelSR-ProhibitTimer-r12 ENUMERATED {sf20, sf40, sf64, sf128, sf512, sf1024, sf2560, spare1} + } + } OPTIONAL -- Need ON + ]], + [[ drx-Config-v1310 DRX-Config-v1310 OPTIONAL, -- Need ON + extendedPHR2-r13 BOOLEAN OPTIONAL, -- Need ON + eDRX-Config-CycleStartOffset-r13 CHOICE { + release NULL, + setup + CHOICE { + sf5120 INTEGER(0..1), + sf10240 INTEGER(0..3) + } + } OPTIONAL -- Need ON + ]], + [[ drx-Config-r13 CHOICE { + release NULL, + setup DRX-Config-r13 + } OPTIONAL -- Need ON + ]], + [[ skipUplinkTx-r14 CHOICE { + release NULL, + setup SEQUENCE { + skipUplinkTxSPS-r14 ENUMERATED {true} OPTIONAL, -- Need OR + skipUplinkTxDynamic-r14 ENUMERATED {true} OPTIONAL -- Need OR + } + } OPTIONAL -- Need ON + ]] +} + +MAC-MainConfigSCell-r11 ::= SEQUENCE { + stag-Id-r11 STAG-Id-r11 OPTIONAL, -- Need OP + ... +} + +DRX-Config ::= CHOICE { + release NULL, + setup SEQUENCE { + onDurationTimer ENUMERATED { + psf1, psf2, psf3, psf4, psf5, psf6, + psf8, psf10, psf20, psf30, psf40, + psf50, psf60, psf80, psf100, + psf200}, + drx-InactivityTimer ENUMERATED { + psf1, psf2, psf3, psf4, psf5, psf6, + psf8, psf10, psf20, psf30, psf40, + psf50, psf60, psf80, psf100, + psf200, psf300, psf500, psf750, + psf1280, psf1920, psf2560, psf0-v1020, + spare9, spare8, spare7, spare6, + spare5, spare4, spare3, spare2, + spare1}, + drx-RetransmissionTimer ENUMERATED { + psf1, psf2, psf4, psf6, psf8, psf16, + psf24, psf33}, + longDRX-CycleStartOffset CHOICE { + sf10 INTEGER(0..9), + sf20 INTEGER(0..19), + sf32 INTEGER(0..31), + sf40 INTEGER(0..39), + sf64 INTEGER(0..63), + sf80 INTEGER(0..79), + sf128 INTEGER(0..127), + sf160 INTEGER(0..159), + sf256 INTEGER(0..255), + sf320 INTEGER(0..319), + sf512 INTEGER(0..511), + sf640 INTEGER(0..639), + sf1024 INTEGER(0..1023), + sf1280 INTEGER(0..1279), + sf2048 INTEGER(0..2047), + sf2560 INTEGER(0..2559) + }, + shortDRX SEQUENCE { + shortDRX-Cycle ENUMERATED { + sf2, sf5, sf8, sf10, sf16, sf20, + sf32, sf40, sf64, sf80, sf128, sf160, + sf256, sf320, sf512, sf640}, + drxShortCycleTimer INTEGER (1..16) + } OPTIONAL -- Need OR + } +} + +DRX-Config-v1130 ::= SEQUENCE { + drx-RetransmissionTimer-v1130 ENUMERATED {psf0-v1130} OPTIONAL, --Need OR + longDRX-CycleStartOffset-v1130 CHOICE { + sf60-v1130 INTEGER(0..59), + sf70-v1130 INTEGER(0..69) + } OPTIONAL, --Need OR + shortDRX-Cycle-v1130 ENUMERATED {sf4-v1130} OPTIONAL --Need OR +} +DRX-Config-v1310 ::= SEQUENCE { + longDRX-CycleStartOffset-v1310 SEQUENCE { + sf60-v1310 INTEGER(0..59) + } OPTIONAL --Need OR +} + +DRX-Config-r13 ::= SEQUENCE { + onDurationTimer-v1310 ENUMERATED {psf300, psf400, psf500, psf600, + psf800, psf1000, psf1200, psf1600} OPTIONAL, --Need OR + drx-RetransmissionTimer-v1310 ENUMERATED {psf40, psf64, psf80, psf96, psf112, + psf128, psf160, psf320} + OPTIONAL, --Need OR + drx-ULRetransmissionTimer-r13 ENUMERATED {psf0, psf1, psf2, psf4, psf6, psf8, psf16, + psf24, psf33, psf40, psf64, psf80, psf96, + psf112, psf128, psf160, psf320} + OPTIONAL --Need OR +} + +PeriodicBSR-Timer-r12 ::= ENUMERATED { + sf5, sf10, sf16, sf20, sf32, sf40, sf64, sf80, + sf128, sf160, sf320, sf640, sf1280, sf2560, + infinity, spare1} + +RetxBSR-Timer-r12 ::= ENUMERATED { + sf320, sf640, sf1280, sf2560, sf5120, + sf10240, spare2, spare1} + +STAG-ToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxSTAG-r11)) OF STAG-Id-r11 + +STAG-ToAddModList-r11 ::= SEQUENCE (SIZE (1..maxSTAG-r11)) OF STAG-ToAddMod-r11 + +STAG-ToAddMod-r11 ::= SEQUENCE { + stag-Id-r11 STAG-Id-r11, + timeAlignmentTimerSTAG-r11 TimeAlignmentTimer, + ... +} + +STAG-Id-r11::= INTEGER (1..maxSTAG-r11) + + +P-C-AndCBSR-r11 ::= SEQUENCE { + p-C-r11 INTEGER (-8..15), + codebookSubsetRestriction-r11 BIT STRING +} + +P-C-AndCBSR-r13 ::= SEQUENCE { + p-C-r13 INTEGER (-8..15), + cbsr-Selection-r13 CHOICE{ + nonPrecoded-r13 SEQUENCE { + codebookSubsetRestriction1-r13 BIT STRING, + codebookSubsetRestriction2-r13 BIT STRING + }, + beamformedK1a-r13 SEQUENCE { + codebookSubsetRestriction3-r13 BIT STRING + }, + beamformedKN-r13 SEQUENCE { + codebookSubsetRestriction-r13 BIT STRING + } + }, + ... +} + +P-C-AndCBSR-Pair-r13a ::= SEQUENCE (SIZE (1..2)) OF P-C-AndCBSR-r11 + +P-C-AndCBSR-Pair-r13 ::= SEQUENCE (SIZE (1..2)) OF P-C-AndCBSR-r13 + + +PDCCH-ConfigSCell-r13 ::= SEQUENCE { + skipMonitoringDCI-format0-1A-r13 ENUMERATED {true} OPTIONAL -- Need OR +} + +PDCCH-ConfigLAA-r14 ::= SEQUENCE { + enableMonitoringDCI-Format0B-r14 CHOICE { + release NULL, + setup SEQUENCE { + maxNumberOfSchedSubframes-Format0B-r14 ENUMERATED {sf2, sf3, sf4} + } + } OPTIONAL, -- Need ON + enableMonitoringDCI-Format4B-r14 CHOICE { + release NULL, + setup SEQUENCE { + maxNumberOfSchedSubframes-Format4B-r14 ENUMERATED {sf2, sf3, sf4} + } + } OPTIONAL, -- Need ON + skipMonitoringDCI-Format0A-r14 ENUMERATED {true} OPTIONAL, -- Need OR + skipMonitoringDCI-Format4A-r14 ENUMERATED {true} OPTIONAL, -- Need OR + pdcch-CandidateReductions-Format0A-r14 + PDCCH-CandidateReductions-r13 OPTIONAL, -- Need ON + pdcch-CandidateReductions-Format4A-r14 + PDCCH-CandidateReductionsLAA-UL-r14 OPTIONAL, -- Need ON + pdcch-CandidateReductions-Format0B-r14 + PDCCH-CandidateReductionsLAA-UL-r14 OPTIONAL, -- Need ON + pdcch-CandidateReductions-Format4B-r14 + PDCCH-CandidateReductionsLAA-UL-r14 OPTIONAL -- Need ON +} + +PDCCH-CandidateReductionValue-r13 ::= ENUMERATED {n0, n33, n66, n100} + +PDCCH-CandidateReductionValue-r14 ::= ENUMERATED {n0, n50, n100, n150} + +PDCCH-CandidateReductions-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + pdcch-candidateReductionAL1-r13 PDCCH-CandidateReductionValue-r13, + pdcch-candidateReductionAL2-r13 PDCCH-CandidateReductionValue-r13, + pdcch-candidateReductionAL3-r13 PDCCH-CandidateReductionValue-r13, + pdcch-candidateReductionAL4-r13 PDCCH-CandidateReductionValue-r13, + pdcch-candidateReductionAL5-r13 PDCCH-CandidateReductionValue-r13 + } +} + +PDCCH-CandidateReductionsLAA-UL-r14 ::= CHOICE { + release NULL, + setup SEQUENCE { + pdcch-candidateReductionAL1-r14 PDCCH-CandidateReductionValue-r13, + pdcch-candidateReductionAL2-r14 PDCCH-CandidateReductionValue-r13, + pdcch-candidateReductionAL3-r14 PDCCH-CandidateReductionValue-r14, + pdcch-candidateReductionAL4-r14 PDCCH-CandidateReductionValue-r14, + pdcch-candidateReductionAL5-r14 PDCCH-CandidateReductionValue-r14 + } +} + + +PDCP-Config ::= SEQUENCE { + discardTimer ENUMERATED { + ms50, ms100, ms150, ms300, ms500, + ms750, ms1500, infinity + } OPTIONAL, -- Cond Setup + rlc-AM SEQUENCE { + statusReportRequired BOOLEAN + } OPTIONAL, -- Cond Rlc-AM + rlc-UM SEQUENCE { + pdcp-SN-Size ENUMERATED {len7bits, len12bits} + } OPTIONAL, -- Cond Rlc-UM + headerCompression CHOICE { + notUsed NULL, + rohc SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + ... + } + }, + ..., + [[ rn-IntegrityProtection-r10 ENUMERATED {enabled} OPTIONAL -- Cond RN + ]], + [[ pdcp-SN-Size-v1130 ENUMERATED {len15bits} OPTIONAL -- Cond Rlc-AM2 + ]], + [[ ul-DataSplitDRB-ViaSCG-r12 BOOLEAN OPTIONAL, -- Need ON + t-Reordering-r12 ENUMERATED { + ms0, ms20, ms40, ms60, ms80, ms100, ms120, ms140, + ms160, ms180, ms200, ms220, ms240, ms260, ms280, ms300, + ms500, ms750, spare14, spare13, spare12, spare11, spare10, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, + spare2, spare1} OPTIONAL -- Cond SetupS + ]], + [[ ul-DataSplitThreshold-r13 CHOICE { + release NULL, + setup ENUMERATED { + b0, b100, b200, b400, b800, b1600, b3200, b6400, b12800, + b25600, b51200, b102400, b204800, b409600, b819200, + spare1} + } OPTIONAL, -- Need ON + pdcp-SN-Size-v1310 ENUMERATED {len18bits} OPTIONAL, -- Cond Rlc-AM3 + statusFeedback-r13 CHOICE { + release NULL, + setup SEQUENCE { + statusPDU-TypeForPolling-r13 ENUMERATED {type1, type2} OPTIONAL, -- Need ON + statusPDU-Periodicity-Type1-r13 ENUMERATED { + ms5, ms10, ms20, ms30, ms40, ms50, ms60, ms70, ms80, ms90, + ms100, ms150, ms200, ms300, ms500, ms1000, ms2000, ms5000, + ms10000, ms20000, ms50000} OPTIONAL, -- Need ON + statusPDU-Periodicity-Type2-r13 ENUMERATED { + ms5, ms10, ms20, ms30, ms40, ms50, ms60, ms70, ms80, ms90, + ms100, ms150, ms200, ms300, ms500, ms1000, ms2000, ms5000, + ms10000, ms20000, ms50000} OPTIONAL, -- Need ON + statusPDU-Periodicity-Offset-r13 ENUMERATED { + ms1, ms2, ms5, ms10, ms25, ms50, ms100, ms250, ms500, + ms2500, ms5000, ms25000} OPTIONAL -- Need ON + } + } OPTIONAL -- Need ON + ]] + +} + + +PDSCH-ConfigCommon ::= SEQUENCE { + referenceSignalPower INTEGER (-60..50), + p-b INTEGER (0..3) +} + +PDSCH-ConfigCommon-v1310 ::= SEQUENCE { + pdsch-maxNumRepetitionCEmodeA-r13 ENUMERATED { + r16, r32 } OPTIONAL, -- Need OR + pdsch-maxNumRepetitionCEmodeB-r13 ENUMERATED { + r192, r256, r384, r512, r768, r1024, + r1536, r2048} OPTIONAL -- Need OR +} + +PDSCH-ConfigDedicated::= SEQUENCE { + p-a ENUMERATED { + dB-6, dB-4dot77, dB-3, dB-1dot77, + dB0, dB1, dB2, dB3} +} + +PDSCH-ConfigDedicated-v1130 ::= SEQUENCE { + dmrs-ConfigPDSCH-r11 DMRS-Config-r11 OPTIONAL, -- Need ON + qcl-Operation ENUMERATED {typeA, typeB} OPTIONAL, -- Need OR + re-MappingQCLConfigToReleaseList-r11 RE-MappingQCLConfigToReleaseList-r11 OPTIONAL, -- Need ON + re-MappingQCLConfigToAddModList-r11 RE-MappingQCLConfigToAddModList-r11 OPTIONAL -- Need ON +} + +PDSCH-ConfigDedicated-v1280 ::= SEQUENCE { + tbsIndexAlt-r12 ENUMERATED {a26, a33} OPTIONAL -- Need OR +} + +PDSCH-ConfigDedicated-v1310 ::= SEQUENCE { + dmrs-ConfigPDSCH-v1310 DMRS-Config-v1310 OPTIONAL -- Need ON +} + +RE-MappingQCLConfigToAddModList-r11 ::= SEQUENCE (SIZE (1..maxRE-MapQCL-r11)) OF PDSCH-RE-MappingQCL-Config-r11 + +RE-MappingQCLConfigToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxRE-MapQCL-r11)) OF PDSCH-RE-MappingQCL-ConfigId-r11 + +PDSCH-RE-MappingQCL-Config-r11 ::= SEQUENCE { + pdsch-RE-MappingQCL-ConfigId-r11 PDSCH-RE-MappingQCL-ConfigId-r11, + optionalSetOfFields-r11 SEQUENCE { + crs-PortsCount-r11 ENUMERATED {n1, n2, n4, spare1}, + crs-FreqShift-r11 INTEGER (0..5), + mbsfn-SubframeConfigList-r11 CHOICE { + release NULL, + setup SEQUENCE { + subframeConfigList MBSFN-SubframeConfigList + } + } OPTIONAL, -- Need ON + pdsch-Start-r11 ENUMERATED {reserved, n1, n2, n3, n4, assigned} + } OPTIONAL, -- Need OP + csi-RS-ConfigZPId-r11 CSI-RS-ConfigZPId-r11, + qcl-CSI-RS-ConfigNZPId-r11 CSI-RS-ConfigNZPId-r11 OPTIONAL, -- Need OR + ... +} + + +PDSCH-RE-MappingQCL-ConfigId-r11 ::= INTEGER (1..maxRE-MapQCL-r11) + + +PHICH-Config ::= SEQUENCE { + phich-Duration ENUMERATED {normal, extended}, + phich-Resource ENUMERATED {oneSixth, half, one, two} +} + + +PhysicalConfigDedicated ::= SEQUENCE { + pdsch-ConfigDedicated PDSCH-ConfigDedicated OPTIONAL, -- Need ON + pucch-ConfigDedicated PUCCH-ConfigDedicated OPTIONAL, -- Need ON + pusch-ConfigDedicated PUSCH-ConfigDedicated OPTIONAL, -- Need ON + uplinkPowerControlDedicated UplinkPowerControlDedicated OPTIONAL, -- Need ON + tpc-PDCCH-ConfigPUCCH TPC-PDCCH-Config OPTIONAL, -- Need ON + tpc-PDCCH-ConfigPUSCH TPC-PDCCH-Config OPTIONAL, -- Need ON + cqi-ReportConfig CQI-ReportConfig OPTIONAL, -- Cond CQI-r8 + soundingRS-UL-ConfigDedicated SoundingRS-UL-ConfigDedicated OPTIONAL, -- Need ON + antennaInfo CHOICE { + explicitValue AntennaInfoDedicated, + defaultValue NULL + } OPTIONAL, -- Cond AI-r8 + schedulingRequestConfig SchedulingRequestConfig OPTIONAL, -- Need ON + ..., + [[ cqi-ReportConfig-v920 CQI-ReportConfig-v920 OPTIONAL, -- Cond CQI-r8 + antennaInfo-v920 AntennaInfoDedicated-v920 OPTIONAL -- Cond AI-r8 + ]], + [[ antennaInfo-r10 CHOICE { + explicitValue-r10 AntennaInfoDedicated-r10, + defaultValue NULL + } OPTIONAL, -- Cond AI-r10 + antennaInfoUL-r10 AntennaInfoUL-r10 OPTIONAL, -- Need ON + cif-Presence-r10 BOOLEAN OPTIONAL, -- Need ON + cqi-ReportConfig-r10 CQI-ReportConfig-r10 OPTIONAL, -- Cond CQI-r10 + csi-RS-Config-r10 CSI-RS-Config-r10 OPTIONAL, -- Need ON + pucch-ConfigDedicated-v1020 PUCCH-ConfigDedicated-v1020 OPTIONAL, -- Need ON + pusch-ConfigDedicated-v1020 PUSCH-ConfigDedicated-v1020 OPTIONAL, -- Need ON + schedulingRequestConfig-v1020 SchedulingRequestConfig-v1020 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicated-v1020 + SoundingRS-UL-ConfigDedicated-v1020 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedAperiodic-r10 + SoundingRS-UL-ConfigDedicatedAperiodic-r10 OPTIONAL, -- Need ON + uplinkPowerControlDedicated-v1020 + UplinkPowerControlDedicated-v1020 OPTIONAL -- Need ON + ]], + [[ additionalSpectrumEmissionCA-r10 CHOICE { + release NULL, + setup SEQUENCE { + additionalSpectrumEmissionPCell-r10 AdditionalSpectrumEmission + } + } OPTIONAL -- Need ON + ]], + [[ -- DL configuration as well as configuration applicable for DL and UL + csi-RS-ConfigNZPToReleaseList-r11 + CSI-RS-ConfigNZPToReleaseList-r11 OPTIONAL, -- Need ON + csi-RS-ConfigNZPToAddModList-r11 + CSI-RS-ConfigNZPToAddModList-r11 OPTIONAL, -- Need ON + csi-RS-ConfigZPToReleaseList-r11 + CSI-RS-ConfigZPToReleaseList-r11 OPTIONAL, -- Need ON + csi-RS-ConfigZPToAddModList-r11 CSI-RS-ConfigZPToAddModList-r11 OPTIONAL, -- Need ON + epdcch-Config-r11 EPDCCH-Config-r11 OPTIONAL, -- Need ON + pdsch-ConfigDedicated-v1130 PDSCH-ConfigDedicated-v1130 OPTIONAL, -- Need ON + -- UL configuration + cqi-ReportConfig-v1130 CQI-ReportConfig-v1130 OPTIONAL, -- Need ON + pucch-ConfigDedicated-v1130 PUCCH-ConfigDedicated-v1130 OPTIONAL, -- Need ON + pusch-ConfigDedicated-v1130 PUSCH-ConfigDedicated-v1130 OPTIONAL, -- Need ON + uplinkPowerControlDedicated-v1130 + UplinkPowerControlDedicated-v1130 OPTIONAL -- Need ON + ]], + [[ antennaInfo-v1250 AntennaInfoDedicated-v1250 OPTIONAL, -- Cond AI-r10 + eimta-MainConfig-r12 EIMTA-MainConfig-r12 OPTIONAL, -- Need ON + eimta-MainConfigPCell-r12 EIMTA-MainConfigServCell-r12 OPTIONAL, -- Need ON + pucch-ConfigDedicated-v1250 PUCCH-ConfigDedicated-v1250 OPTIONAL, -- Need ON + cqi-ReportConfigPCell-v1250 CQI-ReportConfig-v1250 OPTIONAL, -- Need ON + uplinkPowerControlDedicated-v1250 + UplinkPowerControlDedicated-v1250 OPTIONAL, -- Need ON + pusch-ConfigDedicated-v1250 PUSCH-ConfigDedicated-v1250 OPTIONAL, -- Need ON + csi-RS-Config-v1250 CSI-RS-Config-v1250 OPTIONAL -- Need ON + ]], + [[ pdsch-ConfigDedicated-v1280 PDSCH-ConfigDedicated-v1280 OPTIONAL -- Need ON + ]], + [[ pdsch-ConfigDedicated-v1310 PDSCH-ConfigDedicated-v1310 OPTIONAL, -- Need ON + pucch-ConfigDedicated-r13 PUCCH-ConfigDedicated-r13 OPTIONAL, -- Need ON + pusch-ConfigDedicated-r13 PUSCH-ConfigDedicated-r13 OPTIONAL, -- Need ON + pdcch-CandidateReductions-r13 + PDCCH-CandidateReductions-r13 OPTIONAL, -- Need ON + cqi-ReportConfig-v1310 CQI-ReportConfig-v1310 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicated-v1310 + SoundingRS-UL-ConfigDedicated-v1310 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedUpPTsExt-r13 + SoundingRS-UL-ConfigDedicatedUpPTsExt-r13 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedAperiodic-v1310 + SoundingRS-UL-ConfigDedicatedAperiodic-v1310 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 + SoundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 OPTIONAL, -- Need ON + csi-RS-Config-v1310 CSI-RS-Config-v1310 OPTIONAL, -- Need ON + ce-Mode-r13 CHOICE { + release NULL, + setup ENUMERATED {ce-ModeA,ce-ModeB} + } OPTIONAL, -- Need ON + csi-RS-ConfigNZPToAddModListExt-r13 CSI-RS-ConfigNZPToAddModListExt-r13 OPTIONAL, -- Need ON + csi-RS-ConfigNZPToReleaseListExt-r13 CSI-RS-ConfigNZPToReleaseListExt-r13 OPTIONAL -- Need ON + ]], + [[ cqi-ReportConfig-v1320 CQI-ReportConfig-v1320 OPTIONAL -- Need ON + ]], + [[ typeA-SRS-TPC-PDCCH-Group-r14 SEQUENCE (SIZE (1..32)) OF SRS-TPC-PDCCH-Config-r14 OPTIONAL, -- Need ON + must-Config-r14 CHOICE{ + release NULL, + setup SEQUENCE { + k-max-r14 ENUMERATED {l1, l3}, + p-a-must-r14 ENUMERATED { + dB-6, dB-4dot77, dB-3, dB-1dot77, + dB0, dB1, dB2, dB3} OPTIONAL -- Need ON + } + } OPTIONAL -- Need ON + ]] + +} + +PhysicalConfigDedicatedSCell-r10 ::= SEQUENCE { + -- DL configuration as well as configuration applicable for DL and UL + nonUL-Configuration-r10 SEQUENCE { + antennaInfo-r10 + AntennaInfoDedicated-r10 OPTIONAL, -- Need ON + crossCarrierSchedulingConfig-r10 + CrossCarrierSchedulingConfig-r10 OPTIONAL, -- Need ON + csi-RS-Config-r10 CSI-RS-Config-r10 OPTIONAL, -- Need ON + pdsch-ConfigDedicated-r10 PDSCH-ConfigDedicated OPTIONAL -- Need ON + } OPTIONAL, -- Cond SCellAdd + -- UL configuration + ul-Configuration-r10 SEQUENCE { + antennaInfoUL-r10 AntennaInfoUL-r10 OPTIONAL, -- Need ON + pusch-ConfigDedicatedSCell-r10 + PUSCH-ConfigDedicatedSCell-r10 OPTIONAL, -- Cond PUSCH-SCell1 + uplinkPowerControlDedicatedSCell-r10 + UplinkPowerControlDedicatedSCell-r10 OPTIONAL, -- Need ON + cqi-ReportConfigSCell-r10 CQI-ReportConfigSCell-r10 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicated-r10 + SoundingRS-UL-ConfigDedicated OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicated-v1020 + SoundingRS-UL-ConfigDedicated-v1020 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedAperiodic-r10 + SoundingRS-UL-ConfigDedicatedAperiodic-r10 OPTIONAL -- Need ON + } OPTIONAL, -- Cond CommonUL + ..., + [[ -- DL configuration as well as configuration applicable for DL and UL + csi-RS-ConfigNZPToReleaseList-r11 + CSI-RS-ConfigNZPToReleaseList-r11 OPTIONAL, -- Need ON + csi-RS-ConfigNZPToAddModList-r11 + CSI-RS-ConfigNZPToAddModList-r11 OPTIONAL, -- Need ON + csi-RS-ConfigZPToReleaseList-r11 + CSI-RS-ConfigZPToReleaseList-r11 OPTIONAL, -- Need ON + csi-RS-ConfigZPToAddModList-r11 + CSI-RS-ConfigZPToAddModList-r11 OPTIONAL, -- Need ON + epdcch-Config-r11 EPDCCH-Config-r11 OPTIONAL, -- Need ON + pdsch-ConfigDedicated-v1130 PDSCH-ConfigDedicated-v1130 OPTIONAL, -- Need ON + -- UL configuration + cqi-ReportConfig-v1130 CQI-ReportConfig-v1130 OPTIONAL, -- Need ON + pusch-ConfigDedicated-v1130 + PUSCH-ConfigDedicated-v1130 OPTIONAL, -- Cond PUSCH-SCell1 + uplinkPowerControlDedicatedSCell-v1130 + UplinkPowerControlDedicated-v1130 OPTIONAL -- Need ON + ]], + [[ antennaInfo-v1250 AntennaInfoDedicated-v1250 OPTIONAL, -- Need ON + eimta-MainConfigSCell-r12 + EIMTA-MainConfigServCell-r12 OPTIONAL, -- Need ON + cqi-ReportConfigSCell-v1250 CQI-ReportConfig-v1250 OPTIONAL, -- Need ON + uplinkPowerControlDedicatedSCell-v1250 + UplinkPowerControlDedicated-v1250 OPTIONAL, -- Need ON + csi-RS-Config-v1250 CSI-RS-Config-v1250 OPTIONAL -- Need ON + ]], + [[ pdsch-ConfigDedicated-v1280 PDSCH-ConfigDedicated-v1280 OPTIONAL -- Need ON + ]], + [[ pucch-Cell-r13 ENUMERATED {true} OPTIONAL, -- Cond PUCCH-SCell1 + pucch-SCell CHOICE{ + release NULL, + setup SEQUENCE { + pucch-ConfigDedicated-r13 + PUCCH-ConfigDedicated-r13 OPTIONAL, -- Need ON + schedulingRequestConfig-r13 + SchedulingRequestConfigSCell-r13 OPTIONAL, -- Need ON + tpc-PDCCH-ConfigPUCCH-SCell-r13 + TPC-PDCCH-ConfigSCell-r13 OPTIONAL, -- Need ON + pusch-ConfigDedicated-r13 + PUSCH-ConfigDedicated-r13 OPTIONAL, -- Cond PUSCH-SCell + uplinkPowerControlDedicated-r13 + UplinkPowerControlDedicatedSCell-v1310 OPTIONAL -- Need ON + } + } OPTIONAL, -- Need ON + crossCarrierSchedulingConfig-r13 + CrossCarrierSchedulingConfig-r13 OPTIONAL, -- Cond Cross-Carrier-Config + pdcch-ConfigSCell-r13 PDCCH-ConfigSCell-r13 OPTIONAL, -- Need ON + cqi-ReportConfig-v1310 CQI-ReportConfig-v1310 OPTIONAL, -- Need ON + pdsch-ConfigDedicated-v1310 PDSCH-ConfigDedicated-v1310 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicated-v1310 + SoundingRS-UL-ConfigDedicated-v1310 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedUpPTsExt-r13 + SoundingRS-UL-ConfigDedicatedUpPTsExt-r13 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedAperiodic-v1310 + SoundingRS-UL-ConfigDedicatedAperiodic-v1310 OPTIONAL, -- Need ON + soundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 + SoundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 OPTIONAL, -- Need ON + csi-RS-Config-v1310 CSI-RS-Config-v1310 OPTIONAL, -- Need ON + laa-SCellConfiguration-r13 LAA-SCellConfiguration-r13 OPTIONAL, -- Need ON + csi-RS-ConfigNZPToAddModListExt-r13 CSI-RS-ConfigNZPToAddModListExt-r13 OPTIONAL, -- Need ON + csi-RS-ConfigNZPToReleaseListExt-r13 CSI-RS-ConfigNZPToReleaseListExt-r13 OPTIONAL -- Need ON + ]], + [[ cqi-ReportConfig-v1320 CQI-ReportConfig-v1320 OPTIONAL -- Need ON + ]], + [[ laa-SCellConfiguration-v14xy LAA-SCellConfiguration-v14xy OPTIONAL, -- Need ON + typeB-SRS-TPC-PDCCH-Config-r14 SRS-TPC-PDCCH-Config-r14 OPTIONAL, -- Need ON + + uplinkPUSCH-LessPowerControlDedicated-v14xy UplinkPUSCH-LessPowerControlDedicated-v14xy OPTIONAL, -- Need ON + soundingRS-UL-PeriodicConfigDedicatedList-r14 SEQUENCE (SIZE (1..2)) OF SoundingRS-UL-ConfigDedicated OPTIONAL, -- Cond PeriodicSRS + soundingRS-UL-PeriodicConfigDedicatedUpPTsExtList-r14 SEQUENCE (SIZE (1..4)) OF SoundingRS-UL-ConfigDedicatedUpPTsExt-r13 OPTIONAL, -- Cond PeriodicSRSExt + + soundingRS-UL-AperiodicConfigDedicatedList-r14 SEQUENCE (SIZE (1..2)) OF SoundingRSAperiodicGroup-r14 OPTIONAL, -- Cond AperiodicSRS + soundingRS-UL-AperiodicConfigDedicatedUpPTsExtList-r14 SEQUENCE (SIZE (1..4)) OF SoundingRSAperiodicGroupUpPTsExt-r14 OPTIONAL, -- Cond AperiodicSRSExt + + must-Config-r14 CHOICE{ + release NULL, + setup SEQUENCE { + k-max-r14 ENUMERATED {l1, l3}, + p-a-must-r14 ENUMERATED { + dB-6, dB-4dot77, dB-3, dB-1dot77, + dB0, dB1, dB2, dB3} OPTIONAL -- Need ON + } + } OPTIONAL -- Need ON + ]] +} + +LAA-SCellConfiguration-r13 ::= SEQUENCE { + subframeStartPosition-r13 ENUMERATED {s0, s07}, + laa-SCellSubframeConfig-r13 BIT STRING (SIZE(8)) +} + +LAA-SCellConfiguration-v14xy ::= SEQUENCE { + crossCarrierSchedulingConfig-UL-r14 CHOICE { + release NULL, + setup SEQUENCE { + crossCarrierSchedulingConfigLAA-UL-r14 CrossCarrierSchedulingConfigLAA-UL-r14 + } + } OPTIONAL, -- Cond Cross-Carrier-ConfigUL + lbt-Config-r14 LBT-Config-r14 OPTIONAL, -- Need ON + pdcch-ConfigLAA-r14 PDCCH-ConfigLAA-r14 OPTIONAL, -- Need ON + absenceOfAnyOtherTechnology-r14 ENUMERATED {true} OPTIONAL, -- Need OR + soundingRS-UL-ConfigDedicatedAperiodic-v14xy + SoundingRS-UL-ConfigDedicatedAperiodic-v14xy OPTIONAL -- Need ON +} + +LBT-Config-r14 ::= CHOICE{ + maxEnergyDetectionThreshold-r14 INTEGER(-85..-52), + energyDetectionThresholdOffset-r14 INTEGER(-13..20) +} + +CSI-RS-ConfigNZPToAddModList-r11 ::= SEQUENCE (SIZE (1..maxCSI-RS-NZP-r11)) OF CSI-RS-ConfigNZP-r11 + +CSI-RS-ConfigNZPToAddModListExt-r13 ::= SEQUENCE (SIZE (1..maxCSI-RS-NZP-v1310)) OF CSI-RS-ConfigNZP-r11 + +CSI-RS-ConfigNZPToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxCSI-RS-NZP-r11)) OF CSI-RS-ConfigNZPId-r11 + +CSI-RS-ConfigNZPToReleaseListExt-r13 ::= SEQUENCE (SIZE (1..maxCSI-RS-NZP-v1310)) OF CSI-RS-ConfigNZPId-v1310 + +CSI-RS-ConfigZPToAddModList-r11 ::= SEQUENCE (SIZE (1..maxCSI-RS-ZP-r11)) OF CSI-RS-ConfigZP-r11 + +CSI-RS-ConfigZPToReleaseList-r11 ::= SEQUENCE (SIZE (1..maxCSI-RS-ZP-r11)) OF CSI-RS-ConfigZPId-r11 + +SoundingRSAperiodicGroup-r14 ::= SEQUENCE{ + srsCcGroupIndexList SEQUENCE (SIZE (1..4)) OF SrsCcGroupIndex OPTIONAL, -- Cond Srs-Trigger-TypeA + soundingRS-UL-ConfigDedicatedAperiodic-r10 SoundingRS-UL-ConfigDedicatedAperiodic-r10 +} + +SoundingRSAperiodicGroupUpPTsExt-r14 ::= SEQUENCE{ + srsCcGroupIndexList SEQUENCE (SIZE (1..4)) OF SrsCcGroupIndex OPTIONAL, -- Cond Srs-Trigger-TypeA + soundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 SoundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 +} + + +P-Max ::= INTEGER (-30..33) + + +PRACH-ConfigSIB ::= SEQUENCE { + rootSequenceIndex INTEGER (0..837), + prach-ConfigInfo PRACH-ConfigInfo +} + +PRACH-ConfigSIB-v1310 ::= SEQUENCE { + rsrp-ThresholdsPrachInfoList-r13 RSRP-ThresholdsPrachInfoList-r13, + mpdcch-startSF-CSS-RA-r13 CHOICE { + fdd-r13 ENUMERATED {v1, v1dot5, v2, v2dot5, v4, v5, v8, + v10}, + tdd-r13 ENUMERATED {v1, v2, v4, v5, v8, v10, v20, spare} + } OPTIONAL, -- Cond MP + prach-HoppingOffset-r13 INTEGER (0..94) OPTIONAL, -- Need OR + prach-ParametersListCE-r13 PRACH-ParametersListCE-r13 +} + +PRACH-Config ::= SEQUENCE { + rootSequenceIndex INTEGER (0..837), + prach-ConfigInfo PRACH-ConfigInfo OPTIONAL -- Need ON +} + +PRACH-Config-v1310 ::= SEQUENCE { + rsrp-ThresholdsPrachInfoList-r13 RSRP-ThresholdsPrachInfoList-r13 OPTIONAL, -- Cond HO + mpdcch-startSF-CSS-RA-r13 CHOICE { + fdd-r13 ENUMERATED {v1, v1dot5, v2, v2dot5, v4, v5, v8, + v10}, + tdd-r13 ENUMERATED {v1, v2, v4, v5, v8, v10, v20, spare} + } OPTIONAL, -- Cond MP + prach-HoppingOffset-r13 INTEGER (0..94) OPTIONAL, -- Need OR + prach-ParametersListCE-r13 PRACH-ParametersListCE-r13 OPTIONAL, -- Cond MP + initial-CE-level-r13 INTEGER (0..3) OPTIONAL -- Need OR +} + +PRACH-Config-v14xy ::= SEQUENCE { + rootSequenceIndexHighSpeed-r14 INTEGER (0..837), + zeroCorrelationZoneConfigHighSpeed-r14 INTEGER (0..12) +} + +PRACH-ConfigSCell-r10 ::= SEQUENCE { + prach-ConfigIndex-r10 INTEGER (0..63) +} + +PRACH-ConfigInfo ::= SEQUENCE { + prach-ConfigIndex INTEGER (0..63), + highSpeedFlag BOOLEAN, + zeroCorrelationZoneConfig INTEGER (0..15), + prach-FreqOffset INTEGER (0..94) +} + +PRACH-ParametersListCE-r13 ::= SEQUENCE (SIZE(1..maxCE-Level-r13)) OF PRACH-ParametersCE-r13 + +PRACH-ParametersCE-r13 ::= SEQUENCE { + prach-ConfigIndex-r13 INTEGER (0..63), + prach-FreqOffset-r13 INTEGER (0..94), + prach-StartingSubframe-r13 ENUMERATED {sf2, sf4, sf8, sf16, sf32, sf64, sf128, + sf256} OPTIONAL, -- Need OP + maxNumPreambleAttemptCE-r13 + ENUMERATED {n3, n4, n5, n6, n7, n8, n10} OPTIONAL, -- Need OP + numRepetitionPerPreambleAttempt-r13 ENUMERATED {n1,n2,n4,n8,n16,n32,n64,n128}, + mpdcch-NarrowbandsToMonitor-r13 SEQUENCE (SIZE(1..2)) OF + INTEGER (1..maxAvailNarrowBands-r13), + mpdcch-NumRepetition-RA-r13 ENUMERATED {r1, r2, r4, r8, r16, + r32, r64, r128, r256}, + prach-HoppingConfig-r13 ENUMERATED {on,off} +} + +RSRP-ThresholdsPrachInfoList-r13 ::= SEQUENCE (SIZE(1..3)) OF RSRP-Range + + +PresenceAntennaPort1 ::= BOOLEAN + + +PUCCH-ConfigCommon ::= SEQUENCE { + deltaPUCCH-Shift ENUMERATED {ds1, ds2, ds3}, + nRB-CQI INTEGER (0..98), + nCS-AN INTEGER (0..7), + n1PUCCH-AN INTEGER (0..2047) +} + +PUCCH-ConfigCommon-v1310 ::= SEQUENCE { + n1PUCCH-AN-InfoList-r13 N1PUCCH-AN-InfoList-r13 OPTIONAL, -- Need OR + pucch-NumRepetitionCE-Msg4-Level0-r13 ENUMERATED {n1, n2, n4, n8} OPTIONAL, -- Need OR + pucch-NumRepetitionCE-Msg4-Level1-r13 ENUMERATED {n1, n2, n4, n8} OPTIONAL, -- Need OR + pucch-NumRepetitionCE-Msg4-Level2-r13 ENUMERATED {n4, n8, n16, n32} OPTIONAL, -- Need OR + pucch-NumRepetitionCE-Msg4-Level3-r13 ENUMERATED {n4, n8, n16, n32} OPTIONAL -- Need OR +} + +PUCCH-ConfigDedicated ::= SEQUENCE { + ackNackRepetition CHOICE{ + release NULL, + setup SEQUENCE { + repetitionFactor ENUMERATED {n2, n4, n6, spare1}, + n1PUCCH-AN-Rep INTEGER (0..2047) + } + }, + tdd-AckNackFeedbackMode ENUMERATED {bundling, multiplexing} OPTIONAL -- Cond TDD +} + +PUCCH-ConfigDedicated-v1020 ::= SEQUENCE { + pucch-Format-r10 CHOICE { + format3-r10 SEQUENCE { + n3PUCCH-AN-List-r10 SEQUENCE (SIZE (1..4)) OF INTEGER (0..549) OPTIONAL, -- Need ON + twoAntennaPortActivatedPUCCH-Format3-r10 CHOICE { + release NULL, + setup SEQUENCE { + n3PUCCH-AN-ListP1-r10 SEQUENCE (SIZE (1..4)) OF INTEGER (0..549) + } + } OPTIONAL -- Need ON + }, + channelSelection-r10 SEQUENCE { + n1PUCCH-AN-CS-r10 CHOICE { + release NULL, + setup SEQUENCE { + n1PUCCH-AN-CS-List-r10 SEQUENCE (SIZE (1..2)) OF N1PUCCH-AN-CS-r10 + } + } OPTIONAL -- Need ON + } + } OPTIONAL, -- Need OR + twoAntennaPortActivatedPUCCH-Format1a1b-r10 ENUMERATED {true} OPTIONAL, -- Need OR + simultaneousPUCCH-PUSCH-r10 ENUMERATED {true} OPTIONAL, -- Need OR + n1PUCCH-AN-RepP1-r10 INTEGER (0..2047) OPTIONAL -- Need OR +} + +PUCCH-ConfigDedicated-v1130 ::= SEQUENCE { + n1PUCCH-AN-CS-v1130 CHOICE { + release NULL, + setup SEQUENCE { + n1PUCCH-AN-CS-ListP1-r11 SEQUENCE (SIZE (2..4)) OF INTEGER (0..2047) + } + } OPTIONAL, -- Need ON + nPUCCH-Param-r11 CHOICE { + release NULL, + setup SEQUENCE { + nPUCCH-Identity-r11 INTEGER (0..503), + n1PUCCH-AN-r11 INTEGER (0..2047) + } + } OPTIONAL -- Need ON +} + +PUCCH-ConfigDedicated-v1250 ::= SEQUENCE { + nkaPUCCH-Param-r12 CHOICE { + release NULL, + setup SEQUENCE { + nkaPUCCH-AN-r12 INTEGER (0..2047) + } + } +} + +PUCCH-ConfigDedicated-r13 ::= SEQUENCE { +--Release 8 + ackNackRepetition-r13 CHOICE{ + release NULL, + setup SEQUENCE { + repetitionFactor-r13 ENUMERATED {n2, n4, n6, spare1}, + n1PUCCH-AN-Rep-r13 INTEGER (0..2047) + } + }, + tdd-AckNackFeedbackMode-r13 ENUMERATED {bundling, multiplexing} OPTIONAL, -- Cond TDD +--Release 10 + pucch-Format-r13 CHOICE { + format3-r13 SEQUENCE { + n3PUCCH-AN-List-r13 SEQUENCE (SIZE (1..4)) OF INTEGER (0..549) OPTIONAL, -- Need ON + twoAntennaPortActivatedPUCCH-Format3-r13 CHOICE { + release NULL, + setup SEQUENCE { + n3PUCCH-AN-ListP1-r13 SEQUENCE (SIZE (1..4)) OF INTEGER (0..549) + } + } OPTIONAL -- Need ON + }, + channelSelection-r13 SEQUENCE { + n1PUCCH-AN-CS-r13 CHOICE { + release NULL, + setup SEQUENCE { + n1PUCCH-AN-CS-List-r13 SEQUENCE (SIZE (1..2)) OF N1PUCCH-AN-CS-r10, + n1PUCCH-AN-CS-ListP1-r13 SEQUENCE (SIZE (2..4)) OF INTEGER (0..2047) + } + } OPTIONAL -- Need ON + }, + format4-r13 SEQUENCE { + format4-resourceConfiguration-r13 SEQUENCE (SIZE (4)) OF Format4-resource-r13, + format4-MultiCSI-resourceConfiguration-r13 SEQUENCE (SIZE (1..2)) OF Format4-resource-r13 OPTIONAL -- Need OR + }, + format5-r13 SEQUENCE { + format5-resourceConfiguration-r13 SEQUENCE (SIZE (4)) OF Format5-resource-r13, + format5-MultiCSI-resourceConfiguration-r13 Format5-resource-r13 OPTIONAL -- Need OR + } + } OPTIONAL, -- Need OR + twoAntennaPortActivatedPUCCH-Format1a1b-r13 ENUMERATED {true} OPTIONAL, -- Need OR + simultaneousPUCCH-PUSCH-r13 ENUMERATED {true} OPTIONAL, -- Need OR + n1PUCCH-AN-RepP1-r13 INTEGER (0..2047) OPTIONAL, -- Need OR +--Release 11 + nPUCCH-Param-r13 CHOICE { + release NULL, + setup SEQUENCE { + nPUCCH-Identity-r13 INTEGER (0..503), + n1PUCCH-AN-r13 INTEGER (0..2047) + } + } OPTIONAL, -- Need ON +--Release 12 + nkaPUCCH-Param-r13 CHOICE { + release NULL, + setup SEQUENCE { + nkaPUCCH-AN-r13 INTEGER (0..2047) + } + } OPTIONAL, -- Need ON +--Release 13 + spatialBundlingPUCCH-r13 BOOLEAN, + spatialBundlingPUSCH-r13 BOOLEAN, + harq-TimingTDD-r13 BOOLEAN, + codebooksizeDetermination-r13 ENUMERATED {dai,cc} OPTIONAL, -- Need OR + maximumPayloadCoderate-r13 INTEGER (0..7) OPTIONAL, -- Need OR + pucch-NumRepetitionCE-r13 CHOICE { + release NULL, + setup CHOICE { + modeA SEQUENCE { + pucch-NumRepetitionCE-format1-r13 ENUMERATED {r1, r2, r4, r8}, + pucch-NumRepetitionCE-format2-r13 ENUMERATED {r1, r2, r4, r8} + }, + modeB SEQUENCE { + pucch-NumRepetitionCE-format1-r13 ENUMERATED {r4, r8, r16, r32}, + pucch-NumRepetitionCE-format2-r13 ENUMERATED {r4, r8, r16, r32} + } + } + } OPTIONAL --Need ON +} + +Format4-resource-r13 ::= SEQUENCE { + startingPRB-format4-r13 INTEGER (0..109), + numberOfPRB-format4-r13 INTEGER (0..7) +} + +Format5-resource-r13 ::= SEQUENCE { + startingPRB-format5-r13 INTEGER (0..109), + cdm-index-format5-r13 INTEGER (0..1) +} + + + +N1PUCCH-AN-CS-r10 ::= SEQUENCE (SIZE (1..4)) OF INTEGER (0..2047) + +N1PUCCH-AN-InfoList-r13 ::= SEQUENCE (SIZE(1..maxCE-Level-r13)) OF INTEGER (0..2047) + + +PUSCH-ConfigCommon ::= SEQUENCE { + pusch-ConfigBasic SEQUENCE { + n-SB INTEGER (1..4), + hoppingMode ENUMERATED {interSubFrame, intraAndInterSubFrame}, + pusch-HoppingOffset INTEGER (0..98), + enable64QAM BOOLEAN + }, + ul-ReferenceSignalsPUSCH UL-ReferenceSignalsPUSCH +} + +PUSCH-ConfigCommon-v1270 ::= SEQUENCE { + enable64QAM-v1270 ENUMERATED {true} +} + +PUSCH-ConfigCommon-v1310 ::= SEQUENCE { + pusch-maxNumRepetitionCEmodeA-r13 ENUMERATED { + r8, r16, r32 } OPTIONAL, -- Need OR + pusch-maxNumRepetitionCEmodeB-r13 ENUMERATED { + r192, r256, r384, r512, r768, r1024, + r1536, r2048} OPTIONAL, -- Need OR + pusch-HoppingOffset-v1310 + INTEGER (1..maxAvailNarrowBands-r13) OPTIONAL -- Need OR +} + +PUSCH-ConfigDedicated ::= SEQUENCE { + betaOffset-ACK-Index INTEGER (0..15), + betaOffset-RI-Index INTEGER (0..15), + betaOffset-CQI-Index INTEGER (0..15) +} + +PUSCH-ConfigDedicated-v1020 ::= SEQUENCE { + betaOffsetMC-r10 SEQUENCE { + betaOffset-ACK-Index-MC-r10 INTEGER (0..15), + betaOffset-RI-Index-MC-r10 INTEGER (0..15), + betaOffset-CQI-Index-MC-r10 INTEGER (0..15) + } OPTIONAL, -- Need OR + groupHoppingDisabled-r10 ENUMERATED {true} OPTIONAL, -- Need OR + dmrs-WithOCC-Activated-r10 ENUMERATED {true} OPTIONAL -- Need OR +} + +PUSCH-ConfigDedicated-v1130 ::= SEQUENCE { + pusch-DMRS-r11 CHOICE { + release NULL, + setup SEQUENCE { + nPUSCH-Identity-r11 INTEGER (0..509), + nDMRS-CSH-Identity-r11 INTEGER (0..509) + } + } +} + +PUSCH-ConfigDedicated-v1250::= SEQUENCE { + uciOnPUSCH CHOICE { + release NULL, + setup SEQUENCE { + betaOffset-ACK-Index-SubframeSet2-r12 INTEGER (0..15), + betaOffset-RI-Index-SubframeSet2-r12 INTEGER (0..15), + betaOffset-CQI-Index-SubframeSet2-r12 INTEGER (0..15), + betaOffsetMC-r12 SEQUENCE { + betaOffset-ACK-Index-MC-SubframeSet2-r12 INTEGER (0..15), + betaOffset-RI-Index-MC-SubframeSet2-r12 INTEGER (0..15), + betaOffset-CQI-Index-MC-SubframeSet2-r12 INTEGER (0..15) + } OPTIONAL -- Need OR + } + } +} +PUSCH-ConfigDedicated-r13 ::= SEQUENCE { + betaOffset-ACK-Index-r13 INTEGER (0..15), + betaOffset2-ACK-Index-r13 INTEGER (0..15) OPTIONAL, -- Need OR + betaOffset-RI-Index-r13 INTEGER (0..15), + betaOffset-CQI-Index-r13 INTEGER (0..15), + betaOffsetMC-r13 SEQUENCE { + betaOffset-ACK-Index-MC-r13 INTEGER (0..15), + betaOffset2-ACK-Index-MC-r13 INTEGER (0..15) OPTIONAL, -- Need OR + betaOffset-RI-Index-MC-r13 INTEGER (0..15), + betaOffset-CQI-Index-MC-r13 INTEGER (0..15) + } OPTIONAL, -- Need OR + groupHoppingDisabled-r13 ENUMERATED {true} OPTIONAL, -- Need OR + dmrs-WithOCC-Activated-r13 ENUMERATED {true} OPTIONAL, -- Need OR + pusch-DMRS-r11 CHOICE { + release NULL, + setup SEQUENCE { + nPUSCH-Identity-r13 INTEGER (0..509), + nDMRS-CSH-Identity-r13 INTEGER (0..509) + } + } OPTIONAL, -- Need ON + uciOnPUSCH CHOICE { + release NULL, + setup SEQUENCE { + betaOffset-ACK-Index-SubframeSet2-r13 INTEGER (0..15), + betaOffset2-ACK-Index-SubframeSet2-r13 INTEGER (0..15) OPTIONAL, -- Need OR + betaOffset-RI-Index-SubframeSet2-r13 INTEGER (0..15), + betaOffset-CQI-Index-SubframeSet2-r13 INTEGER (0..15), + betaOffsetMC-r12 SEQUENCE { + betaOffset-ACK-Index-MC-SubframeSet2-r13 INTEGER (0..15), + betaOffset2-ACK-Index-MC-SubframeSet2-r13 INTEGER (0..15) OPTIONAL, -- Need OR + betaOffset-RI-Index-MC-SubframeSet2-r13 INTEGER (0..15), + betaOffset-CQI-Index-MC-SubframeSet2-r13 INTEGER (0..15) + } OPTIONAL -- Need OR + } + } OPTIONAL, -- Need ON + pusch-HoppingConfig-r13 ENUMERATED {on} OPTIONAL -- Need OR +} + +PUSCH-ConfigDedicatedSCell-r10 ::= SEQUENCE { + groupHoppingDisabled-r10 ENUMERATED {true} OPTIONAL, -- Need OR + dmrs-WithOCC-Activated-r10 ENUMERATED {true} OPTIONAL -- Need OR +} + +UL-ReferenceSignalsPUSCH ::= SEQUENCE { + groupHoppingEnabled BOOLEAN, + groupAssignmentPUSCH INTEGER (0..29), + sequenceHoppingEnabled BOOLEAN, + cyclicShift INTEGER (0..7) +} + + +RACH-ConfigCommon ::= SEQUENCE { + preambleInfo SEQUENCE { + numberOfRA-Preambles ENUMERATED { + n4, n8, n12, n16, n20, n24, n28, + n32, n36, n40, n44, n48, n52, n56, + n60, n64}, + preamblesGroupAConfig SEQUENCE { + sizeOfRA-PreamblesGroupA ENUMERATED { + n4, n8, n12, n16, n20, n24, n28, + n32, n36, n40, n44, n48, n52, n56, + n60}, + messageSizeGroupA ENUMERATED {b56, b144, b208, b256}, + messagePowerOffsetGroupB ENUMERATED { + minusinfinity, dB0, dB5, dB8, dB10, dB12, + dB15, dB18}, + ... + } OPTIONAL -- Need OP + }, + powerRampingParameters PowerRampingParameters, + ra-SupervisionInfo SEQUENCE { + preambleTransMax PreambleTransMax, + ra-ResponseWindowSize ENUMERATED { + sf2, sf3, sf4, sf5, sf6, sf7, + sf8, sf10}, + mac-ContentionResolutionTimer ENUMERATED { + sf8, sf16, sf24, sf32, sf40, sf48, + sf56, sf64} + }, + maxHARQ-Msg3Tx INTEGER (1..8), + ..., + [[ preambleTransMax-CE-r13 PreambleTransMax OPTIONAL, -- Need OR + rach-CE-LevelInfoList-r13 RACH-CE-LevelInfoList-r13 OPTIONAL -- Need OR + ]] +} + +RACH-ConfigCommon-v1250 ::= SEQUENCE { + txFailParams-r12 SEQUENCE { + connEstFailCount-r12 ENUMERATED {n1, n2, n3, n4}, + connEstFailOffsetValidity-r12 ENUMERATED {s30, s60, s120, s240, + s300, s420, s600, s900}, + connEstFailOffset-r12 INTEGER (0..15) OPTIONAL -- Need OP + } +} + +RACH-ConfigCommonSCell-r11 ::= SEQUENCE { + powerRampingParameters-r11 PowerRampingParameters, + ra-SupervisionInfo-r11 SEQUENCE { + preambleTransMax-r11 PreambleTransMax + }, + ... +} + +RACH-CE-LevelInfoList-r13 ::= SEQUENCE (SIZE (1..maxCE-Level-r13)) OF RACH-CE-LevelInfo-r13 + +RACH-CE-LevelInfo-r13 ::= SEQUENCE { + preambleMappingInfo-r13 SEQUENCE { + firstPreamble-r13 INTEGER(0..63), + lastPreamble-r13 INTEGER(0..63) + }, + ra-ResponseWindowSize-r13 ENUMERATED {sf20, sf50, sf80, sf120, sf180, + sf240, sf320, sf400}, + + mac-ContentionResolutionTimer-r13 ENUMERATED {sf80, sf100, sf120, + sf160, sf200, sf240, sf480, sf960}, + rar-HoppingConfig-r13 ENUMERATED {on,off}, + ... +} + +PowerRampingParameters ::= SEQUENCE { + powerRampingStep ENUMERATED {dB0, dB2,dB4, dB6}, + preambleInitialReceivedTargetPower ENUMERATED { + dBm-120, dBm-118, dBm-116, dBm-114, dBm-112, + dBm-110, dBm-108, dBm-106, dBm-104, dBm-102, + dBm-100, dBm-98, dBm-96, dBm-94, + dBm-92, dBm-90} +} + +PreambleTransMax ::= ENUMERATED { + n3, n4, n5, n6, n7, n8, n10, n20, n50, + n100, n200} + + +RACH-ConfigDedicated ::= SEQUENCE { + ra-PreambleIndex INTEGER (0..63), + ra-PRACH-MaskIndex INTEGER (0..15) +} + + +RadioResourceConfigCommonSIB ::= SEQUENCE { + rach-ConfigCommon RACH-ConfigCommon, + bcch-Config BCCH-Config, + pcch-Config PCCH-Config, + prach-Config PRACH-ConfigSIB, + pdsch-ConfigCommon PDSCH-ConfigCommon, + pusch-ConfigCommon PUSCH-ConfigCommon, + pucch-ConfigCommon PUCCH-ConfigCommon, + soundingRS-UL-ConfigCommon SoundingRS-UL-ConfigCommon, + uplinkPowerControlCommon UplinkPowerControlCommon, + ul-CyclicPrefixLength UL-CyclicPrefixLength, + ..., + [[ uplinkPowerControlCommon-v1020 UplinkPowerControlCommon-v1020 OPTIONAL -- Need OR + ]], + [[ rach-ConfigCommon-v1250 RACH-ConfigCommon-v1250 OPTIONAL -- Need OR + ]], + [[ pusch-ConfigCommon-v1270 PUSCH-ConfigCommon-v1270 OPTIONAL -- Need OR + ]], + [[ bcch-Config-v1310 BCCH-Config-v1310 OPTIONAL, -- Need OR + pcch-Config-v1310 PCCH-Config-v1310 OPTIONAL, -- Need OR + freqHoppingParameters-r13 FreqHoppingParameters-r13 OPTIONAL, -- Need OR + pdsch-ConfigCommon-v1310 PDSCH-ConfigCommon-v1310 OPTIONAL, -- Need OR + pusch-ConfigCommon-v1310 PUSCH-ConfigCommon-v1310 OPTIONAL, -- Need OR + prach-ConfigCommon-v1310 PRACH-ConfigSIB-v1310 OPTIONAL, -- Need OR + pucch-ConfigCommon-v1310 PUCCH-ConfigCommon-v1310 OPTIONAL -- Need OR + ]], + [[ highSpeedConfig-r14 HighSpeedConfig-r14 OPTIONAL, -- Need OR + prach-Config-v14xy PRACH-Config-v14xy OPTIONAL -- Need OR + ]] +} + +RadioResourceConfigCommon ::= SEQUENCE { + rach-ConfigCommon RACH-ConfigCommon OPTIONAL, -- Need ON + prach-Config PRACH-Config, + pdsch-ConfigCommon PDSCH-ConfigCommon OPTIONAL, -- Need ON + pusch-ConfigCommon PUSCH-ConfigCommon, + phich-Config PHICH-Config OPTIONAL, -- Need ON + pucch-ConfigCommon PUCCH-ConfigCommon OPTIONAL, -- Need ON + soundingRS-UL-ConfigCommon SoundingRS-UL-ConfigCommon OPTIONAL, -- Need ON + uplinkPowerControlCommon UplinkPowerControlCommon OPTIONAL, -- Need ON + antennaInfoCommon AntennaInfoCommon OPTIONAL, -- Need ON + p-Max P-Max OPTIONAL, -- Need OP + tdd-Config TDD-Config OPTIONAL, -- Cond TDD + ul-CyclicPrefixLength UL-CyclicPrefixLength, + ..., + [[ uplinkPowerControlCommon-v1020 UplinkPowerControlCommon-v1020 OPTIONAL -- Need ON + ]], + [[ tdd-Config-v1130 TDD-Config-v1130 OPTIONAL -- Cond TDD3 + ]], + [[ pusch-ConfigCommon-v1270 PUSCH-ConfigCommon-v1270 OPTIONAL -- Need OR + ]], + [[ + prach-Config-v1310 PRACH-Config-v1310 OPTIONAL, -- Need ON + freqHoppingParameters-r13 FreqHoppingParameters-r13 OPTIONAL, -- Need ON + pdsch-ConfigCommon-v1310 PDSCH-ConfigCommon-v1310 OPTIONAL, -- Need ON + pucch-ConfigCommon-v1310 PUCCH-ConfigCommon-v1310 OPTIONAL, -- Need ON + pusch-ConfigCommon-v1310 PUSCH-ConfigCommon-v1310 OPTIONAL, -- Need ON + uplinkPowerControlCommon-v1310 UplinkPowerControlCommon-v1310 OPTIONAL -- Need ON + ]], + [[ highSpeedConfig-r14 HighSpeedConfig-r14 OPTIONAL, -- Need OR + prach-Config-v14xy PRACH-Config-v14xy OPTIONAL -- Need OR + ]] +} + +RadioResourceConfigCommonPSCell-r12 ::= SEQUENCE { + basicFields-r12 RadioResourceConfigCommonSCell-r10, + pucch-ConfigCommon-r12 PUCCH-ConfigCommon, + rach-ConfigCommon-r12 RACH-ConfigCommon, + uplinkPowerControlCommonPSCell-r12 UplinkPowerControlCommonPSCell-r12, + ..., + [[ uplinkPowerControlCommonPSCell-v1310 + UplinkPowerControlCommon-v1310 OPTIONAL -- Need ON + ]] +} + +RadioResourceConfigCommonSCell-r10 ::= SEQUENCE { + -- DL configuration as well as configuration applicable for DL and UL + nonUL-Configuration-r10 SEQUENCE { + -- 1: Cell characteristics + dl-Bandwidth-r10 ENUMERATED {n6, n15, n25, n50, n75, n100}, + -- 2: Physical configuration, general + antennaInfoCommon-r10 AntennaInfoCommon, + mbsfn-SubframeConfigList-r10 MBSFN-SubframeConfigList OPTIONAL, -- Need OR + -- 3: Physical configuration, control + phich-Config-r10 PHICH-Config, + -- 4: Physical configuration, physical channels + pdsch-ConfigCommon-r10 PDSCH-ConfigCommon, + tdd-Config-r10 TDD-Config OPTIONAL -- Cond TDDSCell + }, + -- UL configuration + ul-Configuration-r10 SEQUENCE { + ul-FreqInfo-r10 SEQUENCE { + ul-CarrierFreq-r10 ARFCN-ValueEUTRA OPTIONAL, -- Need OP + ul-Bandwidth-r10 ENUMERATED {n6, n15, + n25, n50, n75, n100} OPTIONAL, -- Need OP + additionalSpectrumEmissionSCell-r10 AdditionalSpectrumEmission + }, + p-Max-r10 P-Max OPTIONAL, -- Need OP + uplinkPowerControlCommonSCell-r10 UplinkPowerControlCommonSCell-r10, + -- A special version of IE UplinkPowerControlCommon may be introduced + -- 3: Physical configuration, control + soundingRS-UL-ConfigCommon-r10 SoundingRS-UL-ConfigCommon, + ul-CyclicPrefixLength-r10 UL-CyclicPrefixLength, + -- 4: Physical configuration, physical channels + prach-ConfigSCell-r10 PRACH-ConfigSCell-r10 OPTIONAL, -- Cond TDD-OR-NoR11 + pusch-ConfigCommon-r10 PUSCH-ConfigCommon + } OPTIONAL, -- Need OR + ..., + [[ ul-CarrierFreq-v1090 ARFCN-ValueEUTRA-v9e0 OPTIONAL -- Need OP + ]], + [[ rach-ConfigCommonSCell-r11 RACH-ConfigCommonSCell-r11 OPTIONAL, -- Cond ULSCell + prach-ConfigSCell-r11 PRACH-Config OPTIONAL, -- Cond UL + tdd-Config-v1130 TDD-Config-v1130 OPTIONAL, -- Cond TDD2 + uplinkPowerControlCommonSCell-v1130 + UplinkPowerControlCommonSCell-v1130 OPTIONAL -- Cond UL + ]], + [[ pusch-ConfigCommon-v1270 PUSCH-ConfigCommon-v1270 OPTIONAL -- Need OR + ]], + [[ pucch-ConfigCommon-r13 PUCCH-ConfigCommon OPTIONAL, -- Cond UL + uplinkPowerControlCommonSCell-v1310 + UplinkPowerControlCommonSCell-v1310 OPTIONAL -- Cond UL + ]], + [[ highSpeedConfigSCell-r14 HighSpeedConfigSCell-r14 OPTIONAL, -- Need OR + prach-Config-v14xy PRACH-Config-v14xy OPTIONAL, -- Cond UL + ul-Configuration-r14 SEQUENCE { + ul-FreqInfo-r14 SEQUENCE { + ul-CarrierFreq-r14 ARFCN-ValueEUTRA-r9 OPTIONAL, -- Need OP + ul-Bandwidth-r14 ENUMERATED {n6, n15, + n25, n50, n75, n100} OPTIONAL, -- Need OP + additionalSpectrumEmissionSCell-r14 AdditionalSpectrumEmission + }, + p-Max-r14 P-Max OPTIONAL, -- Need OP + soundingRS-UL-ConfigCommon-r14 SoundingRS-UL-ConfigCommon, + ul-CyclicPrefixLength-r14 UL-CyclicPrefixLength, + prach-ConfigSCell-r14 PRACH-ConfigSCell-r10 OPTIONAL, -- Cond TDD-OR-NoR11 + uplinkPowerControlCommonPUSCH-LessCell-v14xy UplinkPowerControlCommonPUSCH-LessCell-v14xy OPTIONAL -- Need OR +} OPTIONAL, -- Cond ULSRS + harq-ReferenceConfig-r14 ENUMERATED {sa2,sa4,sa5} OPTIONAL, -- Need OR + soundingRS-FlexibleTiming-r14 ENUMERATED {true} OPTIONAL -- Need OR + ]] +} + +BCCH-Config ::= SEQUENCE { + modificationPeriodCoeff ENUMERATED {n2, n4, n8, n16} +} + +BCCH-Config-v1310 ::= SEQUENCE { + modificationPeriodCoeff-v1310 ENUMERATED {n64} +} + +FreqHoppingParameters-r13 ::= SEQUENCE { + mpdcch-pdsch-HoppingNB-r13 ENUMERATED {nb2, nb4} OPTIONAL, -- Cond HO + interval-DLHoppingConfigCommonModeA-r13 CHOICE { + interval-FDD-r13 ENUMERATED {int1, int2, int4, int8}, + interval-TDD-r13 ENUMERATED {int1, int5, int10, int20} + } OPTIONAL, -- Cond HO + interval-DLHoppingConfigCommonModeB-r13 CHOICE { + interval-FDD-r13 ENUMERATED {int2, int4, int8, int16}, + interval-TDD-r13 ENUMERATED { int5, int10, int20, int40} + } OPTIONAL, -- Cond HO + interval-ULHoppingConfigCommonModeA-r13 CHOICE { + interval-FDD-r13 ENUMERATED {int1, int2, int4, int8}, + interval-TDD-r13 ENUMERATED {int1, int5, int10, int20} + } OPTIONAL, -- Cond MP-A + interval-ULHoppingConfigCommonModeB-r13 CHOICE { + interval-FDD-r13 ENUMERATED {int2, int4, int8, int16}, + interval-TDD-r13 ENUMERATED { int5, int10, int20, int40} + } OPTIONAL, -- Cond MP-B + mpdcch-pdsch-HoppingOffset-r13 INTEGER (1..maxAvailNarrowBands-r13) + OPTIONAL -- Cond HO +} + +PCCH-Config ::= SEQUENCE { + defaultPagingCycle ENUMERATED { + rf32, rf64, rf128, rf256}, + nB ENUMERATED { + fourT, twoT, oneT, halfT, quarterT, oneEighthT, + oneSixteenthT, oneThirtySecondT} +} + +PCCH-Config-v1310 ::= SEQUENCE { + paging-narrowBands-r13 INTEGER (1..maxAvailNarrowBands-r13), + mpdcch-NumRepetition-Paging-r13 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, r128, r256}, + nB-v1310 ENUMERATED {one64thT, one128thT, one256thT} + OPTIONAL -- Need OR +} + +UL-CyclicPrefixLength ::= ENUMERATED {len1, len2} + +HighSpeedConfig-r14 ::= SEQUENCE { + highSpeedEnhancedMeasFlag-r14 ENUMERATED {true} OPTIONAL, -- Need OR + highSpeedEnhancedDemodulationFlag-r14 ENUMERATED {true} OPTIONAL -- Need OR +} + +HighSpeedConfigSCell-r14 ::= SEQUENCE { + highSpeedEnhancedDemodulationFlag-r14 ENUMERATED {true} OPTIONAL -- Need OR +} + + +RadioResourceConfigDedicated ::= SEQUENCE { + srb-ToAddModList SRB-ToAddModList OPTIONAL, -- Cond HO-Conn + drb-ToAddModList DRB-ToAddModList OPTIONAL, -- Cond HO-toEUTRA + drb-ToReleaseList DRB-ToReleaseList OPTIONAL, -- Need ON + mac-MainConfig CHOICE { + explicitValue MAC-MainConfig, + defaultValue NULL + } OPTIONAL, -- Cond HO-toEUTRA2 + sps-Config SPS-Config OPTIONAL, -- Need ON + physicalConfigDedicated PhysicalConfigDedicated OPTIONAL, -- Need ON + ..., + [[ rlf-TimersAndConstants-r9 RLF-TimersAndConstants-r9 OPTIONAL -- Need ON + ]], + [[ measSubframePatternPCell-r10 MeasSubframePatternPCell-r10 OPTIONAL -- Need ON + ]], + [[ neighCellsCRS-Info-r11 NeighCellsCRS-Info-r11 OPTIONAL -- Need ON + ]], + [[ naics-Info-r12 NAICS-AssistanceInfo-r12 OPTIONAL -- Need ON + ]], + [[ neighCellsCRS-Info-r13 NeighCellsCRS-Info-r13 OPTIONAL, -- Cond CRSIM + rlf-TimersAndConstants-r13 RLF-TimersAndConstants-r13 OPTIONAL -- Need ON + ]] +} + +RadioResourceConfigDedicatedPSCell-r12 ::= SEQUENCE { + -- UE specific configuration extensions applicable for an PSCell + physicalConfigDedicatedPSCell-r12 PhysicalConfigDedicated OPTIONAL, -- Need ON + sps-Config-r12 SPS-Config OPTIONAL, -- Need ON + naics-Info-r12 NAICS-AssistanceInfo-r12 OPTIONAL, -- Need ON + ..., + [[ neighCellsCRS-InfoPSCell-r13 NeighCellsCRS-Info-r13 OPTIONAL -- Need ON + ]] +} + +RadioResourceConfigDedicatedSCG-r12 ::= SEQUENCE { + drb-ToAddModListSCG-r12 DRB-ToAddModListSCG-r12 OPTIONAL, -- Need ON + mac-MainConfigSCG-r12 MAC-MainConfig OPTIONAL, -- Need ON + rlf-TimersAndConstantsSCG-r12 RLF-TimersAndConstantsSCG-r12 OPTIONAL, -- Need ON + ... +} + +RadioResourceConfigDedicatedSCell-r10 ::= SEQUENCE { + -- UE specific configuration extensions applicable for an SCell + physicalConfigDedicatedSCell-r10 PhysicalConfigDedicatedSCell-r10 OPTIONAL, -- Need ON + ..., + [[ mac-MainConfigSCell-r11 MAC-MainConfigSCell-r11 OPTIONAL -- Cond SCellAdd + ]], + [[ naics-Info-r12 NAICS-AssistanceInfo-r12 OPTIONAL -- Need ON + ]], + [[ neighCellsCRS-InfoSCell-r13 NeighCellsCRS-Info-r13 OPTIONAL -- Need ON + ]] + +} + +SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod + +SRB-ToAddMod ::= SEQUENCE { + srb-Identity INTEGER (1..2), + rlc-Config CHOICE { + explicitValue RLC-Config, + defaultValue NULL + } OPTIONAL, -- Cond Setup + logicalChannelConfig CHOICE { + explicitValue LogicalChannelConfig, + defaultValue NULL + } OPTIONAL, -- Cond Setup + ... +} + +DRB-ToAddModList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddMod + +DRB-ToAddModListSCG-r12 ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddModSCG-r12 + +DRB-ToAddMod ::= SEQUENCE { + eps-BearerIdentity INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup + drb-Identity DRB-Identity, + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + rlc-Config RLC-Config OPTIONAL, -- Cond SetupM + logicalChannelIdentity INTEGER (3..10) OPTIONAL, -- Cond DRB-SetupM + logicalChannelConfig LogicalChannelConfig OPTIONAL, -- Cond SetupM + ..., + [[ drb-TypeChange-r12 ENUMERATED {toMCG} OPTIONAL, -- Need OP + rlc-Config-v1250 RLC-Config-v1250 OPTIONAL -- Need ON + ]], + [[ rlc-Config-v1310 RLC-Config-v1310 OPTIONAL, -- Need ON + drb-TypeLWA-r13 BOOLEAN OPTIONAL, -- Need ON + drb-TypeLWIP-r13 ENUMERATED {lwip, lwip-DL-only, + lwip-UL-only, eutran} OPTIONAL -- Need ON + ]], + [[ rlc-Config-v14xy RLC-Config-v14xy OPTIONAL, -- Need ON + lwip-UL-Aggregation-r14 BOOLEAN OPTIONAL, -- Cond LWIP + lwip-DL-Aggregation-r14 BOOLEAN OPTIONAL -- Cond LWIP + ]] +} + +DRB-ToAddModSCG-r12 ::= SEQUENCE { + drb-Identity-r12 DRB-Identity, + drb-Type-r12 CHOICE { + split-r12 NULL, + scg-r12 SEQUENCE { + eps-BearerIdentity-r12 INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup + pdcp-Config-r12 PDCP-Config OPTIONAL -- Cond PDCP-S + } + } OPTIONAL, -- Cond SetupS2 + rlc-ConfigSCG-r12 RLC-Config OPTIONAL, -- Cond SetupS + rlc-Config-v1250 RLC-Config-v1250 OPTIONAL, -- Need ON + logicalChannelIdentitySCG-r12 INTEGER (3..10) OPTIONAL, -- Cond DRB-SetupS + logicalChannelConfigSCG-r12 LogicalChannelConfig OPTIONAL, -- Cond SetupS + ..., + [[ rlc-Config-v14xy RLC-Config-v14xy OPTIONAL -- Need ON + ]] +} + +DRB-ToReleaseList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-Identity + +MeasSubframePatternPCell-r10 ::= CHOICE { + release NULL, + setup MeasSubframePattern-r10 +} + +NeighCellsCRS-Info-r11 ::= CHOICE { + release NULL, + setup CRS-AssistanceInfoList-r11 +} + +CRS-AssistanceInfoList-r11 ::= SEQUENCE (SIZE (1..maxCellReport)) OF CRS-AssistanceInfo-r11 + +CRS-AssistanceInfo-r11 ::= SEQUENCE { + physCellId-r11 PhysCellId, + antennaPortsCount-r11 ENUMERATED {an1, an2, an4, spare1}, + mbsfn-SubframeConfigList-r11 MBSFN-SubframeConfigList, + ... +} + +NeighCellsCRS-Info-r13 ::= CHOICE { + release NULL, + setup CRS-AssistanceInfoList-r13 +} + +CRS-AssistanceInfoList-r13 ::= SEQUENCE (SIZE (1..maxCellReport)) OF CRS-AssistanceInfo-r13 + +CRS-AssistanceInfo-r13 ::= SEQUENCE { + physCellId-r13 PhysCellId, + antennaPortsCount-r13 ENUMERATED {an1, an2, an4, spare1}, + mbsfn-SubframeConfigList-r13 MBSFN-SubframeConfigList OPTIONAL, -- Need ON + ... +} + +NAICS-AssistanceInfo-r12 ::= CHOICE { + release NULL, + setup SEQUENCE { + neighCellsToReleaseList-r12 NeighCellsToReleaseList-r12 OPTIONAL , -- Need ON + neighCellsToAddModList-r12 NeighCellsToAddModList-r12 OPTIONAL, -- Need ON + servCellp-a-r12 P-a OPTIONAL -- Need ON + } +} + +NeighCellsToReleaseList-r12 ::= SEQUENCE (SIZE (1..maxNeighCell-r12)) OF PhysCellId + +NeighCellsToAddModList-r12 ::= SEQUENCE (SIZE (1..maxNeighCell-r12)) OF NeighCellsInfo-r12 + +NeighCellsInfo-r12 ::= SEQUENCE { + physCellId-r12 PhysCellId, + p-b-r12 INTEGER (0..3), + crs-PortsCount-r12 ENUMERATED {n1, n2, n4, spare}, + mbsfn-SubframeConfig-r12 MBSFN-SubframeConfigList OPTIONAL, -- Need ON + p-aList-r12 SEQUENCE (SIZE (1..maxP-a-PerNeighCell-r12)) OF P-a, + transmissionModeList-r12 BIT STRING (SIZE(8)), + resAllocGranularity-r12 INTEGER (1..4), + ... +} +P-a ::= ENUMERATED { dB-6, dB-4dot77, dB-3, dB-1dot77, + dB0, dB1, dB2, dB3} + + +RCLWI-Configuration-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + rclwi-Config-r13 RCLWI-Config-r13 + } +} + +RCLWI-Config-r13 ::= SEQUENCE { + command CHOICE { + steerToWLAN-r13 SEQUENCE { + mobilityConfig-r13 WLAN-Id-List-r12 + }, + steerToLTE-r13 NULL + }, + ... +} + + +RLC-Config ::= CHOICE { + am SEQUENCE { + ul-AM-RLC UL-AM-RLC, + dl-AM-RLC DL-AM-RLC + }, + um-Bi-Directional SEQUENCE { + ul-UM-RLC UL-UM-RLC, + dl-UM-RLC DL-UM-RLC + }, + um-Uni-Directional-UL SEQUENCE { + ul-UM-RLC UL-UM-RLC + }, + um-Uni-Directional-DL SEQUENCE { + dl-UM-RLC DL-UM-RLC + }, + ... +} + +RLC-Config-v1250 ::= SEQUENCE { + ul-extended-RLC-LI-Field-r12 BOOLEAN, + dl-extended-RLC-LI-Field-r12 BOOLEAN +} + +RLC-Config-v1310 ::= SEQUENCE { + ul-extended-RLC-AM-SN-r13 BOOLEAN, + dl-extended-RLC-AM-SN-r13 BOOLEAN, + pollPDU-v1310 PollPDU-v1310 OPTIONAL -- Need OR +} + +RLC-Config-v14xy ::= CHOICE { + release NULL, + setup SEQUENCE { + pollByte-r14 PollByte-r14 + } +} + +UL-AM-RLC ::= SEQUENCE { + t-PollRetransmit T-PollRetransmit, + pollPDU PollPDU, + pollByte PollByte, + maxRetxThreshold ENUMERATED { + t1, t2, t3, t4, t6, t8, t16, t32} +} + +DL-AM-RLC ::= SEQUENCE { + t-Reordering T-Reordering, + t-StatusProhibit T-StatusProhibit +} + +UL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLength +} + +DL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLength, + t-Reordering T-Reordering +} + +SN-FieldLength ::= ENUMERATED {size5, size10} + +T-PollRetransmit ::= ENUMERATED { + ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800-v1310, + ms1000-v1310, ms2000-v1310, ms4000-v1310, + spare5, spare4, spare3, spare2, spare1} + +PollPDU ::= ENUMERATED { + p4, p8, p16, p32, p64, p128, p256, pInfinity} + +PollPDU-v1310 ::= ENUMERATED { + p512, p1024, p2048, p4096, p6144, p8192, p12288, p16384} + +PollByte ::= ENUMERATED { + kB25, kB50, kB75, kB100, kB125, kB250, kB375, + kB500, kB750, kB1000, kB1250, kB1500, kB2000, + kB3000, kBinfinity, spare1} + +PollByte-r14 ::= ENUMERATED { + kB1, kB2, kB5, kB8, kB10, kB15, kB3500, + kB4000, kB4500, kB5000, kB5500, kB6000, kB6500, + kB7000, kB7500, kB8000, kB9000, kB10000, kB11000, kB12000, + kB13000, kB14000, kB15000, kB16000, kB17000, kB18000, + kB19000, kB20000, kB25000, kB30000, kB35000, kB40000} + +T-Reordering ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms110, + ms120, ms130, ms140, ms150, ms160, ms170, + ms180, ms190, ms200, ms1600-v1310} + +T-StatusProhibit ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800-v1310, + ms1000-v1310, ms1200-v1310, ms1600-v1310, ms2000-v1310, ms2400-v1310, spare2, + spare1} + + +RLF-TimersAndConstants-r9 ::= CHOICE { + release NULL, + setup SEQUENCE { + t301-r9 ENUMERATED { + ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, + ms2000}, + t310-r9 ENUMERATED { + ms0, ms50, ms100, ms200, ms500, ms1000, ms2000}, + n310-r9 ENUMERATED { + n1, n2, n3, n4, n6, n8, n10, n20}, + t311-r9 ENUMERATED { + ms1000, ms3000, ms5000, ms10000, ms15000, + ms20000, ms30000}, + n311-r9 ENUMERATED { + n1, n2, n3, n4, n5, n6, n8, n10}, + ... + } +} + +RLF-TimersAndConstants-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + t301-v1310 ENUMERATED { + ms2500, ms3000, ms3500, ms4000, ms5000, + ms6000, ms8000, ms10000}, + ..., + [[ t310-v1330 ENUMERATED {ms4000, ms6000} OPTIONAL -- Need ON + ]] + } +} + +RLF-TimersAndConstantsSCG-r12 ::= CHOICE { + release NULL, + setup SEQUENCE { + t313-r12 ENUMERATED { + ms0, ms50, ms100, ms200, ms500, ms1000, ms2000}, + n313-r12 ENUMERATED { + n1, n2, n3, n4, n6, n8, n10, n20}, + n314-r12 ENUMERATED { + n1, n2, n3, n4, n5, n6, n8, n10}, + ... + } +} + + +RN-SubframeConfig-r10 ::= SEQUENCE { + subframeConfigPattern-r10 CHOICE { + subframeConfigPatternFDD-r10 BIT STRING (SIZE(8)), + subframeConfigPatternTDD-r10 INTEGER (0..31) + } OPTIONAL, -- Need ON + rpdcch-Config-r10 SEQUENCE { + resourceAllocationType-r10 ENUMERATED {type0, type1, type2Localized, type2Distributed, + spare4, spare3, spare2, spare1}, + resourceBlockAssignment-r10 CHOICE { + type01-r10 CHOICE { + nrb6-r10 BIT STRING (SIZE(6)), + nrb15-r10 BIT STRING (SIZE(8)), + nrb25-r10 BIT STRING (SIZE(13)), + nrb50-r10 BIT STRING (SIZE(17)), + nrb75-r10 BIT STRING (SIZE(19)), + nrb100-r10 BIT STRING (SIZE(25)) + }, + type2-r10 CHOICE { + nrb6-r10 BIT STRING (SIZE(5)), + nrb15-r10 BIT STRING (SIZE(7)), + nrb25-r10 BIT STRING (SIZE(9)), + nrb50-r10 BIT STRING (SIZE(11)), + nrb75-r10 BIT STRING (SIZE(12)), + nrb100-r10 BIT STRING (SIZE(13)) + }, + ... + }, + demodulationRS-r10 CHOICE { + interleaving-r10 ENUMERATED {crs}, + noInterleaving-r10 ENUMERATED {crs, dmrs} + }, + pdsch-Start-r10 INTEGER (1..3), + pucch-Config-r10 CHOICE { + tdd CHOICE { + channelSelectionMultiplexingBundling SEQUENCE { + n1PUCCH-AN-List-r10 SEQUENCE (SIZE (1..4)) OF INTEGER (0..2047) + }, + fallbackForFormat3 SEQUENCE { + n1PUCCH-AN-P0-r10 INTEGER (0..2047), + n1PUCCH-AN-P1-r10 INTEGER (0..2047) OPTIONAL -- Need OR + } + }, + fdd SEQUENCE { + n1PUCCH-AN-P0-r10 INTEGER (0..2047), + n1PUCCH-AN-P1-r10 INTEGER (0..2047) OPTIONAL -- Need OR + } + }, + ... + } OPTIONAL, -- Need ON + ... +} + + +SchedulingRequestConfig ::= CHOICE { + release NULL, + setup SEQUENCE { + sr-PUCCH-ResourceIndex INTEGER (0..2047), + sr-ConfigIndex INTEGER (0..157), + dsr-TransMax ENUMERATED { + n4, n8, n16, n32, n64, spare3, spare2, spare1} + } +} + +SchedulingRequestConfig-v1020 ::= SEQUENCE { + sr-PUCCH-ResourceIndexP1-r10 INTEGER (0..2047) OPTIONAL -- Need OR +} + +SchedulingRequestConfigSCell-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + sr-PUCCH-ResourceIndex-r13 INTEGER (0..2047), + sr-PUCCH-ResourceIndexP1-r13 INTEGER (0..2047) OPTIONAL, -- Need OR + sr-ConfigIndex-r13 INTEGER (0..157), + dsr-TransMax-r13 ENUMERATED { + n4, n8, n16, n32, n64, spare3, spare2, spare1} + } + +} + + +SoundingRS-UL-ConfigCommon ::= CHOICE { + release NULL, + setup SEQUENCE { + srs-BandwidthConfig ENUMERATED {bw0, bw1, bw2, bw3, bw4, bw5, bw6, bw7}, + srs-SubframeConfig ENUMERATED { + sc0, sc1, sc2, sc3, sc4, sc5, sc6, sc7, + sc8, sc9, sc10, sc11, sc12, sc13, sc14, sc15}, + ackNackSRS-SimultaneousTransmission BOOLEAN, + srs-MaxUpPts ENUMERATED {true} OPTIONAL -- Cond TDD + } +} + +SoundingRS-UL-ConfigDedicated ::= CHOICE{ + release NULL, + setup SEQUENCE { + srs-Bandwidth ENUMERATED {bw0, bw1, bw2, bw3}, + srs-HoppingBandwidth ENUMERATED {hbw0, hbw1, hbw2, hbw3}, + freqDomainPosition INTEGER (0..23), + duration BOOLEAN, + srs-ConfigIndex INTEGER (0..1023), + transmissionComb INTEGER (0..1), + cyclicShift ENUMERATED {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7} + } +} + +SoundingRS-UL-ConfigDedicated-v1020 ::= SEQUENCE { + srs-AntennaPort-r10 SRS-AntennaPort +} + +SoundingRS-UL-ConfigDedicated-v1310 ::= CHOICE{ + release NULL, + setup SEQUENCE { + transmissionComb-v1310 INTEGER (2..3) OPTIONAL, -- Need OR + cyclicShift-v1310 ENUMERATED {cs8, cs9, cs10, cs11} OPTIONAL, -- Need OR + transmissionCombNum-r13 ENUMERATED {n2, n4} OPTIONAL -- Need OR + } +} + +SoundingRS-UL-ConfigDedicatedUpPTsExt-r13 ::= CHOICE{ + release NULL, + setup SEQUENCE { + srs-UpPtsAdd-r13 ENUMERATED {sym2, sym4}, + srs-Bandwidth-r13 ENUMERATED {bw0, bw1, bw2, bw3}, + srs-HoppingBandwidth-r13 ENUMERATED {hbw0, hbw1, hbw2, hbw3}, + freqDomainPosition-r13 INTEGER (0..23), + duration-r13 BOOLEAN, + srs-ConfigIndex-r13 INTEGER (0..1023), + transmissionComb-r13 INTEGER (0..3), + cyclicShift-r13 ENUMERATED {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, + cs8, cs9, cs10, cs11}, + srs-AntennaPort-r13 SRS-AntennaPort, + transmissionCombNum-r13 ENUMERATED {n2, n4} + } +} + +SoundingRS-UL-ConfigDedicatedAperiodic-r10 ::= CHOICE{ + release NULL, + setup SEQUENCE { + srs-ConfigIndexAp-r10 INTEGER (0..31), + srs-ConfigApDCI-Format4-r10 SEQUENCE (SIZE (1..3)) OF SRS-ConfigAp-r10 OPTIONAL,--Need ON + srs-ActivateAp-r10 CHOICE { + release NULL, + setup SEQUENCE { + srs-ConfigApDCI-Format0-r10 SRS-ConfigAp-r10, + srs-ConfigApDCI-Format1a2b2c-r10 SRS-ConfigAp-r10, + ... + } + } OPTIONAL -- Need ON + } +} + +SoundingRS-UL-ConfigDedicatedAperiodic-v1310 ::= CHOICE{ + release NULL, + setup SEQUENCE { + srs-ConfigApDCI-Format4-v1310 SEQUENCE (SIZE (1..3)) OF SRS-ConfigAp-v1310 OPTIONAL,--Need ON + srs-ActivateAp-v1310 CHOICE { + release NULL, + setup SEQUENCE { + srs-ConfigApDCI-Format0-v1310 SRS-ConfigAp-v1310 OPTIONAL, -- Need ON + srs-ConfigApDCI-Format1a2b2c-v1310 SRS-ConfigAp-v1310 OPTIONAL -- Need ON + } + } OPTIONAL -- Need ON + } +} + +SoundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13 ::= CHOICE{ + release NULL, + setup SEQUENCE { + srs-UpPtsAdd-r13 ENUMERATED {sym2, sym4}, + srs-ConfigIndexAp-r13 INTEGER (0..31), + srs-ConfigApDCI-Format4-r13 SEQUENCE (SIZE (1..3)) OF SRS-ConfigAp-r13 OPTIONAL,--Need ON + srs-ActivateAp-r13 CHOICE { + release NULL, + setup SEQUENCE { + srs-ConfigApDCI-Format0-r13 SRS-ConfigAp-r13, + srs-ConfigApDCI-Format1a2b2c-r13 SRS-ConfigAp-r13 + } + } OPTIONAL -- Need ON + } +} + +SoundingRS-UL-ConfigDedicatedAperiodic-v14xy ::= CHOICE{ + release NULL, + setup SEQUENCE { + srs-SubframeIndication-r14 INTEGER (1..4) OPTIONAL -- Need ON + } +} + +SRS-ConfigAp-r10 ::= SEQUENCE { + srs-AntennaPortAp-r10 SRS-AntennaPort, + srs-BandwidthAp-r10 ENUMERATED {bw0, bw1, bw2, bw3}, + freqDomainPositionAp-r10 INTEGER (0..23), + transmissionCombAp-r10 INTEGER (0..1), + cyclicShiftAp-r10 ENUMERATED {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7} +} + +SRS-ConfigAp-v1310 ::= SEQUENCE { + transmissionCombAp-v1310 INTEGER (2..3) OPTIONAL, -- Need OR + cyclicShiftAp-v1310 ENUMERATED {cs8, cs9, cs10, cs11} OPTIONAL, -- Need OR + transmissionCombNum-r13 ENUMERATED {n2, n4} OPTIONAL -- Need OR +} + +SRS-ConfigAp-r13 ::= SEQUENCE { + srs-AntennaPortAp-r13 SRS-AntennaPort, + srs-BandwidthAp-r13 ENUMERATED {bw0, bw1, bw2, bw3}, + freqDomainPositionAp-r13 INTEGER (0..23), + transmissionCombAp-r13 INTEGER (0..3), + cyclicShiftAp-r13 ENUMERATED {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, + cs8, cs9, cs10, cs11}, + transmissionCombNum-r13 ENUMERATED {n2, n4} +} + +SRS-AntennaPort ::= ENUMERATED {an1, an2, an4, spare1} + + +SPS-Config ::= SEQUENCE { + semiPersistSchedC-RNTI C-RNTI OPTIONAL, -- Need OR + sps-ConfigDL SPS-ConfigDL OPTIONAL, -- Need ON + sps-ConfigUL SPS-ConfigUL OPTIONAL -- Need ON +} + +SPS-ConfigDL ::= CHOICE{ + release NULL, + setup SEQUENCE { + semiPersistSchedIntervalDL ENUMERATED { + sf10, sf20, sf32, sf40, sf64, sf80, + sf128, sf160, sf320, sf640, spare6, + spare5, spare4, spare3, spare2, + spare1}, + numberOfConfSPS-Processes INTEGER (1..8), + n1PUCCH-AN-PersistentList N1PUCCH-AN-PersistentList, + ..., + [[ twoAntennaPortActivated-r10 CHOICE { + release NULL, + setup SEQUENCE { + n1PUCCH-AN-PersistentListP1-r10 N1PUCCH-AN-PersistentList + } + } OPTIONAL -- Need ON + ]] + } +} + +SPS-ConfigUL ::= CHOICE { + release NULL, + setup SEQUENCE { + semiPersistSchedIntervalUL ENUMERATED { + sf10, sf20, sf32, sf40, sf64, sf80, + sf128, sf160, sf320, sf640, sf1-v14xy, + sf2-v14xy, sf3-v14xy, sf4-v14xy, sf5-v14xy, + spare1}, + implicitReleaseAfter ENUMERATED {e2, e3, e4, e8}, + p0-Persistent SEQUENCE { + p0-NominalPUSCH-Persistent INTEGER (-126..24), + p0-UE-PUSCH-Persistent INTEGER (-8..7) + } OPTIONAL, -- Need OP + twoIntervalsConfig ENUMERATED {true} OPTIONAL, -- Cond TDD + ..., + [[ p0-PersistentSubframeSet2-r12 CHOICE { + release NULL, + setup SEQUENCE { + p0-NominalPUSCH-PersistentSubframeSet2-r12 INTEGER (-126..24), + p0-UE-PUSCH-PersistentSubframeSet2-r12 INTEGER (-8..7) + } + } OPTIONAL -- Need ON + ]], + [[ numberOfConfUlSPS-Processes-r13 INTEGER (1..8) OPTIONAL -- Need OR + ]], + [[ fixedRV-NonAdaptive-r14 ENUMERATED {true} OPTIONAL -- Need OR + ]] + } +} + +N1PUCCH-AN-PersistentList ::= SEQUENCE (SIZE (1..4)) OF INTEGER (0..2047) + + +SRS-TPC-PDCCH-Config-r14 ::= CHOICE { + release NULL, + setup SEQUENCE { + srs-TPC-RNTI-r14 BIT STRING (SIZE (16)), + startingBitOfFormat3B-r14 INTEGER (0..31), fieldTypeFormat3B-r14 INTEGER (1..4), + srsCcGroupIndexlist SEQUENCE (SIZE(1..4)) OF SrsCcGroupIndex OPTIONAL -- Cond Srs-Trigger-TypeA + + } +} + +SrsCcGroupIndex ::= INTEGER (0..3) + +TDD-Config ::= SEQUENCE { + subframeAssignment ENUMERATED { + sa0, sa1, sa2, sa3, sa4, sa5, sa6}, + specialSubframePatterns ENUMERATED { + ssp0, ssp1, ssp2, ssp3, ssp4,ssp5, ssp6, ssp7, + ssp8} +} + +TDD-Config-v1130 ::= SEQUENCE { + specialSubframePatterns-v1130 ENUMERATED {ssp7,ssp9} +} + +TDD-ConfigSL-r12 ::= SEQUENCE { + subframeAssignmentSL-r12 ENUMERATED { + none, sa0, sa1, sa2, sa3, sa4, sa5, sa6} +} + + +TimeAlignmentTimer ::= ENUMERATED { + sf500, sf750, sf1280, sf1920, sf2560, sf5120, + sf10240, infinity} + +TPC-PDCCH-Config ::= CHOICE { + release NULL, + setup SEQUENCE { + tpc-RNTI BIT STRING (SIZE (16)), + tpc-Index TPC-Index + } +} + +TPC-PDCCH-ConfigSCell-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + tpc-Index-PUCCH-SCell-r13 TPC-Index + } +} + +TPC-Index ::= CHOICE { + indexOfFormat3 INTEGER (1..15), + indexOfFormat3A INTEGER (1..31) +} + + +TunnelConfigLWIP-r13 ::= SEQUENCE { + ip-Address-r13 IP-Address-r13, + ike-Identity-r13 IKE-Identity-r13, + ..., + [[ lwip-Counter-r13 INTEGER (0..65535) OPTIONAL -- Cond LWIP-Setup + ]] +} + +IKE-Identity-r13 ::= SEQUENCE { + idI-r13 OCTET STRING +} + +IP-Address-r13 ::= CHOICE { + ipv4-r13 BIT STRING (SIZE (32)), + ipv6-r13 BIT STRING (SIZE (128)) +} + + +UplinkPowerControlCommon ::= SEQUENCE { + p0-NominalPUSCH INTEGER (-126..24), + alpha Alpha-r12, + p0-NominalPUCCH INTEGER (-127..-96), + deltaFList-PUCCH DeltaFList-PUCCH, + deltaPreambleMsg3 INTEGER (-1..6) +} + +UplinkPowerControlCommon-v1020 ::= SEQUENCE { + deltaF-PUCCH-Format3-r10 ENUMERATED {deltaF-1, deltaF0, deltaF1, deltaF2, + deltaF3, deltaF4, deltaF5, deltaF6}, + deltaF-PUCCH-Format1bCS-r10 ENUMERATED {deltaF1, deltaF2, spare2, spare1} +} + +UplinkPowerControlCommon-v1310 ::= SEQUENCE { + deltaF-PUCCH-Format4-r13 ENUMERATED {deltaF16, deltaF15, deltaF14,deltaF13, deltaF12, + deltaF11, deltaF10, spare1} OPTIONAL, -- Need OR + deltaF-PUCCH-Format5-13 ENUMERATED { deltaF13, deltaF12, deltaF11, deltaF10, deltaF9, + deltaF8, deltaF7, spare1} OPTIONAL -- Need OR +} + +UplinkPowerControlCommonPSCell-r12 ::= SEQUENCE { +-- For uplink power control the additional/ missing fields are signalled (compared to SCell) + deltaF-PUCCH-Format3-r12 ENUMERATED {deltaF-1, deltaF0, deltaF1, deltaF2, + deltaF3, deltaF4, deltaF5, deltaF6}, + deltaF-PUCCH-Format1bCS-r12 ENUMERATED {deltaF1, deltaF2, spare2, spare1}, + p0-NominalPUCCH-r12 INTEGER (-127..-96), + deltaFList-PUCCH-r12 DeltaFList-PUCCH +} + + +UplinkPowerControlCommonSCell-r10 ::= SEQUENCE { + p0-NominalPUSCH-r10 INTEGER (-126..24), + alpha-r10 Alpha-r12 +} + +UplinkPowerControlCommonSCell-v1130 ::= SEQUENCE { + deltaPreambleMsg3-r11 INTEGER (-1..6) +} + +UplinkPowerControlCommonSCell-v1310 ::= SEQUENCE { +-- For uplink power control the additional/ missing fields are signalled (compared to SCell) + p0-NominalPUCCH INTEGER (-127..-96), + deltaFList-PUCCH DeltaFList-PUCCH, + deltaF-PUCCH-Format3-r12 ENUMERATED {deltaF-1, deltaF0, deltaF1, + deltaF2, deltaF3, deltaF4, deltaF5, + deltaF6} OPTIONAL, -- Need OR + deltaF-PUCCH-Format1bCS-r12 ENUMERATED {deltaF1, deltaF2, + spare2, spare1} OPTIONAL, -- Need OR + deltaF-PUCCH-Format4-r13 ENUMERATED {deltaF16, deltaF15, deltaF14, + deltaF13, deltaF12, deltaF11, deltaF10, + spare1} OPTIONAL, -- Need OR + deltaF-PUCCH-Format5-13 ENUMERATED { deltaF13, deltaF12, deltaF11, + deltaF10, deltaF9, deltaF8, deltaF7, + spare1} OPTIONAL -- Need OR +} +UplinkPowerControlCommonPUSCH-LessCell-v14xy ::= SEQUENCE { + p0-Nominal-PeriodicSRS INTEGER (-126..24) OPTIONAL, -- Need OR + p0-Nominal-AperiodicSRS INTEGER (-126..24) OPTIONAL, -- Need OR + alpha-SRS-r14 Alpha-r12 OPTIONAL -- Need OR +} + +UplinkPowerControlDedicated ::= SEQUENCE { + p0-UE-PUSCH INTEGER (-8..7), + deltaMCS-Enabled ENUMERATED {en0, en1}, + accumulationEnabled BOOLEAN, + p0-UE-PUCCH INTEGER (-8..7), + pSRS-Offset INTEGER (0..15), + filterCoefficient FilterCoefficient DEFAULT fc4 +} + +UplinkPowerControlDedicated-v1020 ::= SEQUENCE { + deltaTxD-OffsetListPUCCH-r10 DeltaTxD-OffsetListPUCCH-r10 OPTIONAL, -- Need OR + pSRS-OffsetAp-r10 INTEGER (0..15) OPTIONAL -- Need OR +} + +UplinkPowerControlDedicated-v1130 ::= SEQUENCE { + pSRS-Offset-v1130 INTEGER (16..31) OPTIONAL, -- Need OR + pSRS-OffsetAp-v1130 INTEGER (16..31) OPTIONAL, -- Need OR + deltaTxD-OffsetListPUCCH-v1130 DeltaTxD-OffsetListPUCCH-v1130 OPTIONAL -- Need OR +} + +UplinkPowerControlDedicated-v1250 ::= SEQUENCE { + set2PowerControlParameter CHOICE { + release NULL, + setup SEQUENCE { + tpc-SubframeSet-r12 BIT STRING (SIZE(10)), + p0-NominalPUSCH-SubframeSet2-r12 INTEGER (-126..24), + alpha-SubframeSet2-r12 Alpha-r12, + p0-UE-PUSCH-SubframeSet2-r12 INTEGER (-8..7) + } + } +} + +UplinkPUSCH-LessPowerControlDedicated-v14xy ::= SEQUENCE { + p0-UE-PeriodicSRS INTEGER (-8..7) OPTIONAL, -- Need OR + p0-UE-AperiodicSRS INTEGER (-8..7) OPTIONAL, -- Need OR + accumulationEnabled BOOLEAN +} + +UplinkPowerControlDedicatedSCell-r10 ::= SEQUENCE { + p0-UE-PUSCH-r10 INTEGER (-8..7), + deltaMCS-Enabled-r10 ENUMERATED {en0, en1}, + accumulationEnabled-r10 BOOLEAN, + pSRS-Offset-r10 INTEGER (0..15), + pSRS-OffsetAp-r10 INTEGER (0..15) OPTIONAL, -- Need OR + filterCoefficient-r10 FilterCoefficient DEFAULT fc4, + pathlossReferenceLinking-r10 ENUMERATED {pCell, sCell} +} + +UplinkPowerControlDedicatedSCell-v1310 ::= SEQUENCE { +--Release 8 + p0-UE-PUCCH INTEGER (-8..7), +--Release 10 + deltaTxD-OffsetListPUCCH-r10 DeltaTxD-OffsetListPUCCH-r10 OPTIONAL -- Need OR +} + +Alpha-r12 ::= ENUMERATED {al0, al04, al05, al06, al07, al08, al09, al1} + +DeltaFList-PUCCH ::= SEQUENCE { + deltaF-PUCCH-Format1 ENUMERATED {deltaF-2, deltaF0, deltaF2}, + deltaF-PUCCH-Format1b ENUMERATED {deltaF1, deltaF3, deltaF5}, + deltaF-PUCCH-Format2 ENUMERATED {deltaF-2, deltaF0, deltaF1, deltaF2}, + deltaF-PUCCH-Format2a ENUMERATED {deltaF-2, deltaF0, deltaF2}, + deltaF-PUCCH-Format2b ENUMERATED {deltaF-2, deltaF0, deltaF2} +} + +DeltaTxD-OffsetListPUCCH-r10 ::= SEQUENCE { + deltaTxD-OffsetPUCCH-Format1-r10 ENUMERATED {dB0, dB-2}, + deltaTxD-OffsetPUCCH-Format1a1b-r10 ENUMERATED {dB0, dB-2}, + deltaTxD-OffsetPUCCH-Format22a2b-r10 ENUMERATED {dB0, dB-2}, + deltaTxD-OffsetPUCCH-Format3-r10 ENUMERATED {dB0, dB-2}, + ... + +} + +DeltaTxD-OffsetListPUCCH-v1130 ::= SEQUENCE { + deltaTxD-OffsetPUCCH-Format1bCS-r11 ENUMERATED {dB0, dB-1} +} + + +WLAN-Id-List-r13 ::= SEQUENCE (SIZE (1..maxWLAN-Id-r13)) OF WLAN-Identifiers-r12 + + +WLAN-MobilityConfig-r13 ::= SEQUENCE { + wlan-ToReleaseList-r13 WLAN-Id-List-r13 OPTIONAL, -- Need ON + wlan-ToAddList-r13 WLAN-Id-List-r13 OPTIONAL, -- Need ON + associationTimer-r13 ENUMERATED {s10, s30, + s60, s120, s240} OPTIONAL, -- Need OR + successReportRequested-r13 ENUMERATED {true} OPTIONAL, -- Need OR + ... +} + + +NextHopChainingCount ::= INTEGER (0..7) + + +SecurityAlgorithmConfig ::= SEQUENCE { + cipheringAlgorithm CipheringAlgorithm-r12, + integrityProtAlgorithm ENUMERATED { + eia0-v920, eia1, eia2, eia3-v1130, spare4, spare3, + spare2, spare1, ...} +} + +CipheringAlgorithm-r12 ::= ENUMERATED { + eea0, eea1, eea2, eea3-v1130, spare4, spare3, + spare2, spare1, ...} + + +ShortMAC-I ::= BIT STRING (SIZE (16)) + + +AdditionalSpectrumEmission ::= INTEGER (1..32) + + +ARFCN-ValueCDMA2000 ::= INTEGER (0..2047) + + +ARFCN-ValueEUTRA ::= INTEGER (0..maxEARFCN) + +ARFCN-ValueEUTRA-v9e0 ::= INTEGER (maxEARFCN-Plus1..maxEARFCN2) + +ARFCN-ValueEUTRA-r9 ::= INTEGER (0..maxEARFCN2) + + +ARFCN-ValueGERAN ::= INTEGER (0..1023) + + +ARFCN-ValueUTRA ::= INTEGER (0..16383) + + +BandclassCDMA2000 ::= ENUMERATED { + bc0, bc1, bc2, bc3, bc4, bc5, bc6, bc7, bc8, + bc9, bc10, bc11, bc12, bc13, bc14, bc15, bc16, + bc17, bc18-v9a0, bc19-v9a0, bc20-v9a0, bc21-v9a0, + spare10, spare9, spare8, spare7, spare6, spare5, spare4, + spare3, spare2, spare1, ...} + + +BandIndicatorGERAN ::= ENUMERATED {dcs1800, pcs1900} + + +CarrierFreqCDMA2000 ::= SEQUENCE { + bandClass BandclassCDMA2000, + arfcn ARFCN-ValueCDMA2000 +} + + +CarrierFreqGERAN ::= SEQUENCE { + arfcn ARFCN-ValueGERAN, + bandIndicator BandIndicatorGERAN +} + + +CarrierFreqsGERAN ::= SEQUENCE { + startingARFCN ARFCN-ValueGERAN, + bandIndicator BandIndicatorGERAN, + followingARFCNs CHOICE { + explicitListOfARFCNs ExplicitListOfARFCNs, + equallySpacedARFCNs SEQUENCE { + arfcn-Spacing INTEGER (1..8), + numberOfFollowingARFCNs INTEGER (0..31) + }, + variableBitMapOfARFCNs OCTET STRING (SIZE (1..16)) + } +} + +ExplicitListOfARFCNs ::= SEQUENCE (SIZE (0..31)) OF ARFCN-ValueGERAN + + +CarrierFreqListMBMS-r11 ::= SEQUENCE (SIZE (1..maxFreqMBMS-r11)) OF ARFCN-ValueEUTRA-r9 + + +CDMA2000-Type ::= ENUMERATED {type1XRTT, typeHRPD} + + +CellIdentity ::= BIT STRING (SIZE (28)) + + +CellIndexList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellIndex + +CellIndex ::= INTEGER (1..maxCellMeas) + + +CellReselectionPriority ::= INTEGER (0..7) + + +CellSelectionInfoCE-r13 ::= SEQUENCE { + q-RxLevMinCE-r13 Q-RxLevMin, + q-QualMinRSRQ-CE-r13 Q-QualMin-r9 OPTIONAL -- Need OR +} + + +CellReselectionSubPriority-r13 ::= ENUMERATED {oDot2, oDot4, oDot6, oDot8} + + +CSFB-RegistrationParam1XRTT ::= SEQUENCE { + sid BIT STRING (SIZE (15)), + nid BIT STRING (SIZE (16)), + multipleSID BOOLEAN, + multipleNID BOOLEAN, + homeReg BOOLEAN, + foreignSIDReg BOOLEAN, + foreignNIDReg BOOLEAN, + parameterReg BOOLEAN, + powerUpReg BOOLEAN, + registrationPeriod BIT STRING (SIZE (7)), + registrationZone BIT STRING (SIZE (12)), + totalZone BIT STRING (SIZE (3)), + zoneTimer BIT STRING (SIZE (3)) +} + +CSFB-RegistrationParam1XRTT-v920 ::= SEQUENCE { + powerDownReg-r9 ENUMERATED {true} +} + + +CellGlobalIdEUTRA ::= SEQUENCE { + plmn-Identity PLMN-Identity, + cellIdentity CellIdentity +} + + +CellGlobalIdUTRA ::= SEQUENCE { + plmn-Identity PLMN-Identity, + cellIdentity BIT STRING (SIZE (28)) +} + + +CellGlobalIdGERAN ::= SEQUENCE { + plmn-Identity PLMN-Identity, + locationAreaCode BIT STRING (SIZE (16)), + cellIdentity BIT STRING (SIZE (16)) +} + + +CellGlobalIdCDMA2000 ::= CHOICE { + cellGlobalId1XRTT BIT STRING (SIZE (47)), + cellGlobalIdHRPD BIT STRING (SIZE (128)) +} + + +CellSelectionInfoNFreq-r13 ::= SEQUENCE { + -- Cell selection information as in SIB1 + q-RxLevMin-r13 Q-RxLevMin, + q-RxLevMinOffset INTEGER (1..8) OPTIONAL, -- Need OP + -- Cell re-selection information as in SIB3 + q-Hyst-r13 ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24}, + q-RxLevMinReselection-r13 Q-RxLevMin, + t-ReselectionEUTRA-r13 T-Reselection +} + + +CSG-Identity ::= BIT STRING (SIZE (27)) + + +FreqBandIndicator ::= INTEGER (1..maxFBI) + +FreqBandIndicator-v9e0 ::= INTEGER (maxFBI-Plus1..maxFBI2) + +FreqBandIndicator-r11 ::= INTEGER (1..maxFBI2) + + +MobilityControlInfo ::= SEQUENCE { + targetPhysCellId PhysCellId, + carrierFreq CarrierFreqEUTRA OPTIONAL, -- Cond HO-toEUTRA2 + carrierBandwidth CarrierBandwidthEUTRA OPTIONAL, -- Cond HO-toEUTRA + additionalSpectrumEmission AdditionalSpectrumEmission OPTIONAL, -- Cond HO-toEUTRA + t304 ENUMERATED { + ms50, ms100, ms150, ms200, ms500, ms1000, + ms2000, ms10000-v1310}, + newUE-Identity C-RNTI, + radioResourceConfigCommon RadioResourceConfigCommon, + rach-ConfigDedicated RACH-ConfigDedicated OPTIONAL, -- Need OP + ..., + [[ carrierFreq-v9e0 CarrierFreqEUTRA-v9e0 OPTIONAL -- Need ON + ]], + [[ drb-ContinueROHC-r11 ENUMERATED {true} OPTIONAL -- Cond HO + ]], + [[ mobilityControlInfoV2X-r14 MobilityControlInfoV2X-r14 OPTIONAL -- Need OR + ]] +} + +MobilityControlInfoSCG-r12 ::= SEQUENCE { + t307-r12 ENUMERATED { + ms50, ms100, ms150, ms200, ms500, ms1000, + ms2000, spare1}, + ue-IdentitySCG-r12 C-RNTI OPTIONAL, -- Cond SCGEst, + rach-ConfigDedicated-r12 RACH-ConfigDedicated OPTIONAL, -- Need OP + cipheringAlgorithmSCG-r12 CipheringAlgorithm-r12 OPTIONAL, -- Need ON + ... +} + +MobilityControlInfoV2X-r14 ::= SEQUENCE { + v2x-CommTxPoolExceptional-r14 SL-CommResourcePoolV2X-r14 OPTIONAL, -- Need OR + v2x-CommRxPool-r14 SL-CommRxPoolListV2X-r14 OPTIONAL, -- Need OR + v2x-CommSyncConfig-r14 SL-SyncConfigListV2X-r14 OPTIONAL -- Need OR +} + +CarrierBandwidthEUTRA ::= SEQUENCE { + dl-Bandwidth ENUMERATED { + n6, n15, n25, n50, n75, n100, spare10, + spare9, spare8, spare7, spare6, spare5, + spare4, spare3, spare2, spare1}, + ul-Bandwidth ENUMERATED { + n6, n15, n25, n50, n75, n100, spare10, + spare9, spare8, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} OPTIONAL -- Need OP +} + +CarrierFreqEUTRA ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueEUTRA, + ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL -- Cond FDD +} + +CarrierFreqEUTRA-v9e0 ::= SEQUENCE { + dl-CarrierFreq-v9e0 ARFCN-ValueEUTRA-r9, + ul-CarrierFreq-v9e0 ARFCN-ValueEUTRA-r9 OPTIONAL -- Cond FDD +} + + +MobilityParametersCDMA2000 ::= OCTET STRING + + +MobilityStateParameters ::= SEQUENCE { + t-Evaluation ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + t-HystNormal ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + n-CellChangeMedium INTEGER (1..16), + n-CellChangeHigh INTEGER (1..16) +} + + +MultiBandInfoList ::= SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicator + +MultiBandInfoList-v9e0 ::= SEQUENCE (SIZE (1..maxMultiBands)) OF MultiBandInfo-v9e0 + +MultiBandInfoList-v10j0 ::= SEQUENCE (SIZE (1..maxMultiBands)) OF NS-PmaxList-r10 + +MultiBandInfoList-r11 ::= SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicator-r11 + +MultiBandInfo-v9e0 ::= SEQUENCE { + freqBandIndicator-v9e0 FreqBandIndicator-v9e0 OPTIONAL -- Need OP +} + + +NS-PmaxList-r10 ::= SEQUENCE (SIZE (1..maxNS-Pmax-r10)) OF NS-PmaxValue-r10 + +NS-PmaxValue-r10 ::= SEQUENCE { + additionalPmax-r10 P-Max OPTIONAL, -- Need OP + additionalSpectrumEmission AdditionalSpectrumEmission +} + + +PhysCellId ::= INTEGER (0..503) + + +PhysCellIdRange ::= SEQUENCE { + start PhysCellId, + range ENUMERATED { + n4, n8, n12, n16, n24, n32, n48, n64, n84, + n96, n128, n168, n252, n504, spare2, + spare1} OPTIONAL -- Need OP +} + + +PhysCellIdRangeUTRA-FDDList-r9::= SEQUENCE (SIZE (1..maxPhysCellIdRange-r9)) OF PhysCellIdRangeUTRA-FDD-r9 + +PhysCellIdRangeUTRA-FDD-r9 ::= SEQUENCE { + start-r9 PhysCellIdUTRA-FDD, + range-r9 INTEGER (2..512) OPTIONAL -- Need OP +} + + +PhysCellIdCDMA2000 ::= INTEGER (0..maxPNOffset) + + +PhysCellIdGERAN ::= SEQUENCE { + networkColourCode BIT STRING (SIZE (3)), + baseStationColourCode BIT STRING (SIZE (3)) +} + + +PhysCellIdUTRA-FDD ::= INTEGER (0..511) + + +PhysCellIdUTRA-TDD ::= INTEGER (0..127) + + +PLMN-Identity ::= SEQUENCE { + mcc MCC OPTIONAL, -- Cond MCC + mnc MNC +} + +MCC ::= SEQUENCE (SIZE (3)) OF + MCC-MNC-Digit + +MNC ::= SEQUENCE (SIZE (2..3)) OF + MCC-MNC-Digit + +MCC-MNC-Digit ::= INTEGER (0..9) + + + +PLMN-IdentityList3-r11 ::= SEQUENCE (SIZE (1..16)) OF PLMN-Identity + + +PreRegistrationInfoHRPD ::= SEQUENCE { + preRegistrationAllowed BOOLEAN, + preRegistrationZoneId PreRegistrationZoneIdHRPD OPTIONAL, -- cond PreRegAllowed + secondaryPreRegistrationZoneIdList SecondaryPreRegistrationZoneIdListHRPD OPTIONAL -- Need OR +} + +SecondaryPreRegistrationZoneIdListHRPD ::= SEQUENCE (SIZE (1..2)) OF PreRegistrationZoneIdHRPD + +PreRegistrationZoneIdHRPD ::= INTEGER (0..255) + + +Q-QualMin-r9 ::= INTEGER (-34..-3) + + +Q-RxLevMin ::= INTEGER (-70..-22) + + +Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + + +Q-OffsetRangeInterRAT ::= INTEGER (-15..15) + + +ReselectionThreshold ::= INTEGER (0..31) + + +ReselectionThresholdQ-r9 ::= INTEGER (0..31) + + +SCellIndex-r10 ::= INTEGER (1..7) +SCellIndex-r13 ::= INTEGER (1..31) + + +ServCellIndex-r10 ::= INTEGER (0..7) +ServCellIndex-r13 ::= INTEGER (0..31) + + +SpeedStateScaleFactors ::= SEQUENCE { + sf-Medium ENUMERATED {oDot25, oDot5, oDot75, lDot0}, + sf-High ENUMERATED {oDot25, oDot5, oDot75, lDot0} +} + +SystemInfoListGERAN ::= SEQUENCE (SIZE (1..maxGERAN-SI)) OF + OCTET STRING (SIZE (1..23)) + + +SystemTimeInfoCDMA2000 ::= SEQUENCE { + cdma-EUTRA-Synchronisation BOOLEAN, + cdma-SystemTime CHOICE { + synchronousSystemTime BIT STRING (SIZE (39)), + asynchronousSystemTime BIT STRING (SIZE (49)) + } +} + + +TrackingAreaCode ::= BIT STRING (SIZE (16)) + + +T-Reselection ::= INTEGER (0..7) + + +T-ReselectionEUTRA-CE-r13 ::= INTEGER (0..15) + + +AllowedMeasBandwidth ::= ENUMERATED {mbw6, mbw15, mbw25, mbw50, mbw75, mbw100} + + +CSI-RSRP-Range-r12 ::= INTEGER(0..97) + + +Hysteresis ::= INTEGER (0..30) + + +LocationInfo-r10 ::= SEQUENCE { + locationCoordinates-r10 CHOICE { + ellipsoid-Point-r10 OCTET STRING, + ellipsoidPointWithAltitude-r10 OCTET STRING, + ..., + ellipsoidPointWithUncertaintyCircle-r11 OCTET STRING, + ellipsoidPointWithUncertaintyEllipse-r11 OCTET STRING, + ellipsoidPointWithAltitudeAndUncertaintyEllipsoid-r11 OCTET STRING, + ellipsoidArc-r11 OCTET STRING, + polygon-r11 OCTET STRING + }, + horizontalVelocity-r10 OCTET STRING OPTIONAL, + gnss-TOD-msec-r10 OCTET STRING OPTIONAL, + ... +} + + +MBSFN-RSRQ-Range-r12 ::= INTEGER(0..31) + +MeasConfig ::= SEQUENCE { + -- Measurement objects + measObjectToRemoveList MeasObjectToRemoveList OPTIONAL, -- Need ON + measObjectToAddModList MeasObjectToAddModList OPTIONAL, -- Need ON + -- Reporting configurations + reportConfigToRemoveList ReportConfigToRemoveList OPTIONAL, -- Need ON + reportConfigToAddModList ReportConfigToAddModList OPTIONAL, -- Need ON + -- Measurement identities + measIdToRemoveList MeasIdToRemoveList OPTIONAL, -- Need ON + measIdToAddModList MeasIdToAddModList OPTIONAL, -- Need ON + -- Other parameters + quantityConfig QuantityConfig OPTIONAL, -- Need ON + measGapConfig MeasGapConfig OPTIONAL, -- Need ON + s-Measure RSRP-Range OPTIONAL, -- Need ON + preRegistrationInfoHRPD PreRegistrationInfoHRPD OPTIONAL, -- Need OP + speedStatePars CHOICE { + release NULL, + setup SEQUENCE { + mobilityStateParameters MobilityStateParameters, + timeToTrigger-SF SpeedStateScaleFactors + } + } OPTIONAL, -- Need ON + ..., + [[ measObjectToAddModList-v9e0 MeasObjectToAddModList-v9e0 OPTIONAL -- Need ON + ]], + [[ allowInterruptions-r11 BOOLEAN OPTIONAL -- Need ON + ]], + [[ measScaleFactor-r12 CHOICE { + release NULL, + setup MeasScaleFactor-r12 + } OPTIONAL, -- Need ON + measIdToRemoveListExt-r12 MeasIdToRemoveListExt-r12 OPTIONAL, -- Need ON + measIdToAddModListExt-r12 MeasIdToAddModListExt-r12 OPTIONAL, -- Need ON + measRSRQ-OnAllSymbols-r12 BOOLEAN OPTIONAL -- Need ON + ]], + [[ + measObjectToRemoveListExt-r13 MeasObjectToRemoveListExt-r13 OPTIONAL, -- Need ON + measObjectToAddModListExt-r13 MeasObjectToAddModListExt-r13 OPTIONAL, -- Need ON + measIdToAddModList-v1310 MeasIdToAddModList-v1310 OPTIONAL, -- Need ON + measIdToAddModListExt-v1310 MeasIdToAddModListExt-v1310 OPTIONAL -- Need ON + ]] +} + +MeasIdToRemoveList ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasId + +MeasIdToRemoveListExt-r12 ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasId-v1250 + +MeasObjectToRemoveList ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectId + +MeasObjectToRemoveListExt-r13 ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectId-v1310 + +ReportConfigToRemoveList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigId + + +MeasDS-Config-r12 ::= CHOICE { + release NULL, + setup SEQUENCE { + dmtc-PeriodOffset-r12 CHOICE { + ms40-r12 INTEGER(0..39), + ms80-r12 INTEGER(0..79), + ms160-r12 INTEGER(0..159), + ... + }, + ds-OccasionDuration-r12 CHOICE { + durationFDD-r12 INTEGER(1..maxDS-Duration-r12), + durationTDD-r12 INTEGER(2..maxDS-Duration-r12) + }, + measCSI-RS-ToRemoveList-r12 MeasCSI-RS-ToRemoveList-r12 OPTIONAL, -- Need ON + measCSI-RS-ToAddModList-r12 MeasCSI-RS-ToAddModList-r12 OPTIONAL, -- Need ON + ... + } +} + +MeasCSI-RS-ToRemoveList-r12 ::= SEQUENCE (SIZE (1..maxCSI-RS-Meas-r12)) OF MeasCSI-RS-Id-r12 + +MeasCSI-RS-ToAddModList-r12 ::= SEQUENCE (SIZE (1..maxCSI-RS-Meas-r12)) OF MeasCSI-RS-Config-r12 + +MeasCSI-RS-Id-r12 ::= INTEGER (1..maxCSI-RS-Meas-r12) + +MeasCSI-RS-Config-r12 ::= SEQUENCE { + measCSI-RS-Id-r12 MeasCSI-RS-Id-r12, + physCellId-r12 INTEGER (0..503), + scramblingIdentity-r12 INTEGER (0..503), + resourceConfig-r12 INTEGER (0..31), + subframeOffset-r12 INTEGER (0..4), + csi-RS-IndividualOffset-r12 Q-OffsetRange, + ... +} + + +MeasGapConfig ::= CHOICE { + release NULL, + setup SEQUENCE { + gapOffset CHOICE { + gp0 INTEGER (0..39), + gp1 INTEGER (0..79), + ... + } + } +} + + +MeasId ::= INTEGER (1..maxMeasId) + +MeasId-v1250 ::= INTEGER (maxMeasId-Plus1..maxMeasId-r12) + + +MeasIdToAddModList ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasIdToAddMod + +MeasIdToAddModList-v1310 ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasIdToAddMod-v1310 + +MeasIdToAddModListExt-r12 ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasIdToAddModExt-r12 + +MeasIdToAddModListExt-v1310 ::= SEQUENCE (SIZE (1..maxMeasId)) OF MeasIdToAddMod-v1310 + +MeasIdToAddMod ::= SEQUENCE { + measId MeasId, + measObjectId MeasObjectId, + reportConfigId ReportConfigId +} + +MeasIdToAddModExt-r12 ::= SEQUENCE { + measId-v1250 MeasId-v1250, + measObjectId-r12 MeasObjectId, + reportConfigId-r12 ReportConfigId +} + +MeasIdToAddMod-v1310 ::= SEQUENCE { + measObjectId-v1310 MeasObjectId-v1310 OPTIONAL +} + + +MeasObjectCDMA2000 ::= SEQUENCE { + cdma2000-Type CDMA2000-Type, + carrierFreq CarrierFreqCDMA2000, + searchWindowSize INTEGER (0..15) OPTIONAL, -- Need ON + offsetFreq Q-OffsetRangeInterRAT DEFAULT 0, + cellsToRemoveList CellIndexList OPTIONAL, -- Need ON + cellsToAddModList CellsToAddModListCDMA2000 OPTIONAL, -- Need ON + cellForWhichToReportCGI PhysCellIdCDMA2000 OPTIONAL, -- Need ON + ... +} + +CellsToAddModListCDMA2000 ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModCDMA2000 + +CellsToAddModCDMA2000 ::= SEQUENCE { + cellIndex INTEGER (1..maxCellMeas), + physCellId PhysCellIdCDMA2000 +} + + +MeasObjectEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + allowedMeasBandwidth AllowedMeasBandwidth, + presenceAntennaPort1 PresenceAntennaPort1, + neighCellConfig NeighCellConfig, + offsetFreq Q-OffsetRange DEFAULT dB0, + -- Cell list + cellsToRemoveList CellIndexList OPTIONAL, -- Need ON + cellsToAddModList CellsToAddModList OPTIONAL, -- Need ON + -- Black list + blackCellsToRemoveList CellIndexList OPTIONAL, -- Need ON + blackCellsToAddModList BlackCellsToAddModList OPTIONAL, -- Need ON + cellForWhichToReportCGI PhysCellId OPTIONAL, -- Need ON + ..., + [[measCycleSCell-r10 MeasCycleSCell-r10 OPTIONAL, -- Need ON + measSubframePatternConfigNeigh-r10 MeasSubframePatternConfigNeigh-r10 OPTIONAL -- Need ON + ]], + [[widebandRSRQ-Meas-r11 BOOLEAN OPTIONAL -- Cond WB-RSRQ + ]], + [[ altTTT-CellsToRemoveList-r12 CellIndexList OPTIONAL, -- Need ON + altTTT-CellsToAddModList-r12 AltTTT-CellsToAddModList-r12 OPTIONAL, -- Need ON + t312-r12 CHOICE { + release NULL, + setup ENUMERATED {ms0, ms50, ms100, ms200, + ms300, ms400, ms500, ms1000} + } OPTIONAL, -- Need ON + reducedMeasPerformance-r12 BOOLEAN OPTIONAL, -- Need ON + measDS-Config-r12 MeasDS-Config-r12 OPTIONAL -- Need ON + ]], + [[ + whiteCellsToRemoveList-r13 CellIndexList OPTIONAL, -- Need ON + whiteCellsToAddModList-r13 WhiteCellsToAddModList-r13 OPTIONAL, -- Need ON + rmtc-Config-r13 RMTC-Config-r13 OPTIONAL, -- Need ON + carrierFreq-r13 ARFCN-ValueEUTRA-v9e0 OPTIONAL -- Need ON + ]] +} + +MeasObjectEUTRA-v9e0 ::= SEQUENCE { + carrierFreq-v9e0 ARFCN-ValueEUTRA-v9e0 +} + +CellsToAddModList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddMod + +CellsToAddMod ::= SEQUENCE { + cellIndex INTEGER (1..maxCellMeas), + physCellId PhysCellId, + cellIndividualOffset Q-OffsetRange +} + +BlackCellsToAddModList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF BlackCellsToAddMod + +BlackCellsToAddMod ::= SEQUENCE { + cellIndex INTEGER (1..maxCellMeas), + physCellIdRange PhysCellIdRange +} + +MeasCycleSCell-r10 ::= ENUMERATED {sf160, sf256, sf320, sf512, + sf640, sf1024, sf1280, spare1} + +MeasSubframePatternConfigNeigh-r10 ::= CHOICE { + release NULL, + setup SEQUENCE { + measSubframePatternNeigh-r10 MeasSubframePattern-r10, + measSubframeCellList-r10 MeasSubframeCellList-r10 OPTIONAL -- Cond always + } +} + +MeasSubframeCellList-r10 ::= SEQUENCE (SIZE (1..maxCellMeas)) OF PhysCellIdRange + +AltTTT-CellsToAddModList-r12 ::= SEQUENCE (SIZE (1..maxCellMeas)) OF AltTTT-CellsToAddMod-r12 + +AltTTT-CellsToAddMod-r12 ::= SEQUENCE { + cellIndex-r12 INTEGER (1..maxCellMeas), + physCellIdRange-r12 PhysCellIdRange +} + +WhiteCellsToAddModList-r13 ::= SEQUENCE (SIZE (1..maxCellMeas)) OF WhiteCellsToAddMod-r13 + +WhiteCellsToAddMod-r13 ::= SEQUENCE { + cellIndex-r13 INTEGER (1..maxCellMeas), + physCellIdRange-r13 PhysCellIdRange +} + +RMTC-Config-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + rmtc-Period-r13 ENUMERATED {ms40, ms80, ms160, ms320, ms640}, + rmtc-SubframeOffset-r13 INTEGER(0..639) OPTIONAL, -- Need ON + measDuration-r13 ENUMERATED {sym1, sym14, sym28, sym42, sym70}, + ... + } +} + + +MeasObjectGERAN ::= SEQUENCE { + carrierFreqs CarrierFreqsGERAN, + offsetFreq Q-OffsetRangeInterRAT DEFAULT 0, + ncc-Permitted BIT STRING(SIZE (8)) DEFAULT '11111111'B, + cellForWhichToReportCGI PhysCellIdGERAN OPTIONAL, -- Need ON + ... +} + + +MeasObjectId ::= INTEGER (1..maxObjectId) + +MeasObjectId-v1310 ::= INTEGER (maxObjectId-Plus1-r13..maxObjectId-r13) + +MeasObjectId-r13 ::= INTEGER (1..maxObjectId-r13) + + +MeasObjectToAddModList ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectToAddMod + +MeasObjectToAddModListExt-r13 ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectToAddModExt-r13 + +MeasObjectToAddModList-v9e0 ::= SEQUENCE (SIZE (1..maxObjectId)) OF MeasObjectToAddMod-v9e0 + +MeasObjectToAddMod ::= SEQUENCE { + measObjectId MeasObjectId, + measObject CHOICE { + measObjectEUTRA MeasObjectEUTRA, + measObjectUTRA MeasObjectUTRA, + measObjectGERAN MeasObjectGERAN, + measObjectCDMA2000 MeasObjectCDMA2000, + ..., + measObjectWLAN-r13 MeasObjectWLAN-r13 + } +} + +MeasObjectToAddModExt-r13 ::= SEQUENCE { + measObjectId-r13 MeasObjectId-v1310, + measObject-r13 CHOICE { + measObjectEUTRA-r13 MeasObjectEUTRA, + measObjectUTRA-r13 MeasObjectUTRA, + measObjectGERAN-r13 MeasObjectGERAN, + measObjectCDMA2000-r13 MeasObjectCDMA2000, + ..., + measObjectWLAN-v1320 MeasObjectWLAN-r13 + } +} + +MeasObjectToAddMod-v9e0 ::= SEQUENCE { + measObjectEUTRA-v9e0 MeasObjectEUTRA-v9e0 OPTIONAL -- Cond eutra +} + + +MeasObjectUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueUTRA, + offsetFreq Q-OffsetRangeInterRAT DEFAULT 0, + cellsToRemoveList CellIndexList OPTIONAL, -- Need ON + cellsToAddModList CHOICE { + cellsToAddModListUTRA-FDD CellsToAddModListUTRA-FDD, + cellsToAddModListUTRA-TDD CellsToAddModListUTRA-TDD + } OPTIONAL, -- Need ON + cellForWhichToReportCGI CHOICE { + utra-FDD PhysCellIdUTRA-FDD, + utra-TDD PhysCellIdUTRA-TDD + } OPTIONAL, -- Need ON + ..., + [[ csg-allowedReportingCells-v930 CSG-AllowedReportingCells-r9 OPTIONAL -- Need ON + ]], + [[ reducedMeasPerformance-r12 BOOLEAN OPTIONAL -- Need ON + ]] +} + +CellsToAddModListUTRA-FDD ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModUTRA-FDD + +CellsToAddModUTRA-FDD ::= SEQUENCE { + cellIndex INTEGER (1..maxCellMeas), + physCellId PhysCellIdUTRA-FDD +} + +CellsToAddModListUTRA-TDD ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CellsToAddModUTRA-TDD + +CellsToAddModUTRA-TDD ::= SEQUENCE { + cellIndex INTEGER (1..maxCellMeas), + physCellId PhysCellIdUTRA-TDD +} + +CSG-AllowedReportingCells-r9 ::= SEQUENCE { + physCellIdRangeUTRA-FDDList-r9 PhysCellIdRangeUTRA-FDDList-r9 OPTIONAL -- Need OR +} + +MeasObjectWLAN-r13 ::= SEQUENCE { + carrierFreq-r13 CHOICE { + bandIndicatorListWLAN-r13 SEQUENCE (SIZE (1..maxWLAN-Bands-r13)) OF WLAN-BandIndicator-r13, + carrierInfoListWLAN-r13 SEQUENCE (SIZE (1..maxWLAN-CarrierInfo-r13)) OF WLAN-CarrierInfo-r13 + } OPTIONAL, -- Need ON + wlan-ToAddModList-r13 WLAN-Id-List-r13 OPTIONAL, -- Need ON + wlan-ToRemoveList-r13 WLAN-Id-List-r13 OPTIONAL, -- Need ON + ... +} + +WLAN-BandIndicator-r13 ::= ENUMERATED {band2dot4, band5, spare6, spare5, spare4, spare3, spare2, spare1, ...} + + +MeasResults ::= SEQUENCE { + measId MeasId, + measResultPCell SEQUENCE { + rsrpResult RSRP-Range, + rsrqResult RSRQ-Range + }, + measResultNeighCells CHOICE { + measResultListEUTRA MeasResultListEUTRA, + measResultListUTRA MeasResultListUTRA, + measResultListGERAN MeasResultListGERAN, + measResultsCDMA2000 MeasResultsCDMA2000, + ... + } OPTIONAL, + ..., + [[ measResultForECID-r9 MeasResultForECID-r9 OPTIONAL + ]], + [[ locationInfo-r10 LocationInfo-r10 OPTIONAL, + measResultServFreqList-r10 MeasResultServFreqList-r10 OPTIONAL + ]], + [[ measId-v1250 MeasId-v1250 OPTIONAL, + measResultPCell-v1250 RSRQ-Range-v1250 OPTIONAL, + measResultCSI-RS-List-r12 MeasResultCSI-RS-List-r12 OPTIONAL + ]], + [[ measResultForRSSI-r13 MeasResultForRSSI-r13 OPTIONAL, + measResultServFreqListExt-r13 MeasResultServFreqListExt-r13 OPTIONAL, + measResultSSTD-r13 MeasResultSSTD-r13 OPTIONAL, + measResultPCell-v1310 SEQUENCE { + rs-sinr-Result-r13 RS-SINR-Range-r13 + } OPTIONAL, + ul-PDCP-DelayResultList-r13 UL-PDCP-DelayResultList-r13 OPTIONAL, + measResultListWLAN-r13 MeasResultListWLAN-r13 OPTIONAL + ]] + +} + +MeasResultListEUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultEUTRA + +MeasResultEUTRA ::= SEQUENCE { + physCellId PhysCellId, + cgi-Info SEQUENCE { + cellGlobalId CellGlobalIdEUTRA, + trackingAreaCode TrackingAreaCode, + plmn-IdentityList PLMN-IdentityList2 OPTIONAL + } OPTIONAL, + measResult SEQUENCE { + rsrpResult RSRP-Range OPTIONAL, + rsrqResult RSRQ-Range OPTIONAL, + ..., + [[ additionalSI-Info-r9 AdditionalSI-Info-r9 OPTIONAL + ]], + [[ primaryPLMN-Suitable-r12 ENUMERATED {true} OPTIONAL, + measResult-v1250 RSRQ-Range-v1250 OPTIONAL + ]], + [[ rs-sinr-Result-r13 RS-SINR-Range-r13 OPTIONAL, + cgi-Info-v1310 SEQUENCE { + freqBandIndicator-r13 FreqBandIndicator-r11 OPTIONAL, + multiBandInfoList-r13 MultiBandInfoList-r11 OPTIONAL, + freqBandIndicatorPriority-r13 ENUMERATED {true} OPTIONAL + } OPTIONAL + ]] + } +} + +MeasResultServFreqList-r10 ::= SEQUENCE (SIZE (1..maxServCell-r10)) OF MeasResultServFreq-r10 + +MeasResultServFreqListExt-r13 ::= SEQUENCE (SIZE (1..maxServCell-r13)) OF MeasResultServFreq-r13 + +MeasResultServFreq-r10 ::= SEQUENCE { + servFreqId-r10 ServCellIndex-r10, + measResultSCell-r10 SEQUENCE { + rsrpResultSCell-r10 RSRP-Range, + rsrqResultSCell-r10 RSRQ-Range + } OPTIONAL, + measResultBestNeighCell-r10 SEQUENCE { + physCellId-r10 PhysCellId, + rsrpResultNCell-r10 RSRP-Range, + rsrqResultNCell-r10 RSRQ-Range + } OPTIONAL, + ..., + [[ measResultSCell-v1250 RSRQ-Range-v1250 OPTIONAL, + measResultBestNeighCell-v1250 RSRQ-Range-v1250 OPTIONAL + ]], + [[ measResultSCell-v1310 SEQUENCE { + rs-sinr-Result-r13 RS-SINR-Range-r13 + } OPTIONAL, + measResultBestNeighCell-v1310 SEQUENCE { + rs-sinr-Result-r13 RS-SINR-Range-r13 + } OPTIONAL + ]] +} + +MeasResultServFreq-r13 ::= SEQUENCE { + servFreqId-r13 ServCellIndex-r13, + measResultSCell-r13 SEQUENCE { + rsrpResultSCell-r13 RSRP-Range, + rsrqResultSCell-r13 RSRQ-Range-r13, + rs-sinr-Result-r13 RS-SINR-Range-r13 OPTIONAL + } OPTIONAL, + measResultBestNeighCell-r13 SEQUENCE { + physCellId-r13 PhysCellId, + rsrpResultNCell-r13 RSRP-Range, + rsrqResultNCell-r13 RSRQ-Range-r13, + rs-sinr-Result-r13 RS-SINR-Range-r13 OPTIONAL + } OPTIONAL, + ... +} + +MeasResultCSI-RS-List-r12 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultCSI-RS-r12 + +MeasResultCSI-RS-r12 ::= SEQUENCE { + measCSI-RS-Id-r12 MeasCSI-RS-Id-r12, + csi-RSRP-Result-r12 CSI-RSRP-Range-r12, + ... +} + +MeasResultListUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultUTRA + +MeasResultUTRA ::= SEQUENCE { + physCellId CHOICE { + fdd PhysCellIdUTRA-FDD, + tdd PhysCellIdUTRA-TDD + }, + cgi-Info SEQUENCE { + cellGlobalId CellGlobalIdUTRA, + locationAreaCode BIT STRING (SIZE (16)) OPTIONAL, + routingAreaCode BIT STRING (SIZE (8)) OPTIONAL, + plmn-IdentityList PLMN-IdentityList2 OPTIONAL + } OPTIONAL, + measResult SEQUENCE { + utra-RSCP INTEGER (-5..91) OPTIONAL, + utra-EcN0 INTEGER (0..49) OPTIONAL, + ..., + [[ additionalSI-Info-r9 AdditionalSI-Info-r9 OPTIONAL + ]], + [[ primaryPLMN-Suitable-r12 ENUMERATED {true} OPTIONAL + ]] + } +} + +MeasResultListGERAN ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultGERAN + +MeasResultGERAN ::= SEQUENCE { + carrierFreq CarrierFreqGERAN, + physCellId PhysCellIdGERAN, + cgi-Info SEQUENCE { + cellGlobalId CellGlobalIdGERAN, + routingAreaCode BIT STRING (SIZE (8)) OPTIONAL + } OPTIONAL, + measResult SEQUENCE { + rssi INTEGER (0..63), + ... + } +} + +MeasResultsCDMA2000 ::= SEQUENCE { + preRegistrationStatusHRPD BOOLEAN, + measResultListCDMA2000 MeasResultListCDMA2000 +} + +MeasResultListCDMA2000 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultCDMA2000 + +MeasResultCDMA2000 ::= SEQUENCE { + physCellId PhysCellIdCDMA2000, + cgi-Info CellGlobalIdCDMA2000 OPTIONAL, + measResult SEQUENCE { + pilotPnPhase INTEGER (0..32767) OPTIONAL, + pilotStrength INTEGER (0..63), + ... + } +} + +MeasResultListWLAN-r13 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultWLAN-r13 + +MeasResultWLAN-r13 ::= SEQUENCE { + wlan-Identifiers-r13 WLAN-Identifiers-r12, + carrierInfoWLAN-r13 WLAN-CarrierInfo-r13 OPTIONAL, + bandWLAN-r13 WLAN-BandIndicator-r13 OPTIONAL, + rssiWLAN-r13 WLAN-RSSI-Range-r13, + availableAdmissionCapacityWLAN-r13 INTEGER (0..31250) OPTIONAL, + backhaulDL-BandwidthWLAN-r13 WLAN-backhaulRate-r12 OPTIONAL, + backhaulUL-BandwidthWLAN-r13 WLAN-backhaulRate-r12 OPTIONAL, + channelUtilizationWLAN-r13 INTEGER (0..255) OPTIONAL, + stationCountWLAN-r13 INTEGER (0..65535) OPTIONAL, + connectedWLAN-r13 ENUMERATED {true} OPTIONAL, + ... +} + +MeasResultForECID-r9 ::= SEQUENCE { + ue-RxTxTimeDiffResult-r9 INTEGER (0..4095), + currentSFN-r9 BIT STRING (SIZE (10)) +} + +PLMN-IdentityList2 ::= SEQUENCE (SIZE (1..5)) OF PLMN-Identity + +AdditionalSI-Info-r9 ::= SEQUENCE { + csg-MemberStatus-r9 ENUMERATED {member} OPTIONAL, + csg-Identity-r9 CSG-Identity OPTIONAL +} +MeasResultForRSSI-r13 ::= SEQUENCE { + rssi-Result-r13 RSSI-Range-r13, + channelOccupancy-r13 INTEGER (0..100), + ... +} + +UL-PDCP-DelayResultList-r13 ::= SEQUENCE (SIZE (1..maxQCI-r13)) OF UL-PDCP-DelayResult-r13 + + +UL-PDCP-DelayResult-r13 ::= SEQUENCE { + qci-Id-r13 ENUMERATED {qci1, qci2, qci3, qci4, spare4, spare3, spare2, spare1}, + excessDelay-r13 INTEGER (0..31), + ... +} + + +MeasResultSSTD-r13 ::= SEQUENCE { + sfn-OffsetResult-r13 INTEGER (0..1023), + frameBoundaryOffsetResult-r13 INTEGER (-5..4), + subframeBoundaryOffsetResult-r13 INTEGER (0..127) +} + + +MeasScaleFactor-r12 ::= ENUMERATED {sf-EUTRA-cf1, sf-EUTRA-cf2} + + +QuantityConfig ::= SEQUENCE { + quantityConfigEUTRA QuantityConfigEUTRA OPTIONAL, -- Need ON + quantityConfigUTRA QuantityConfigUTRA OPTIONAL, -- Need ON + quantityConfigGERAN QuantityConfigGERAN OPTIONAL, -- Need ON + quantityConfigCDMA2000 QuantityConfigCDMA2000 OPTIONAL, -- Need ON + ..., + [[ quantityConfigUTRA-v1020 QuantityConfigUTRA-v1020 OPTIONAL -- Need ON + ]], + [[ quantityConfigEUTRA-v1250 QuantityConfigEUTRA-v1250 OPTIONAL -- Need ON + ]], + [[ quantityConfigEUTRA-v1310 QuantityConfigEUTRA-v1310 OPTIONAL, -- Need ON + quantityConfigWLAN-r13 QuantityConfigWLAN-r13 OPTIONAL -- Need ON + ]] +} + +QuantityConfigEUTRA ::= SEQUENCE { + filterCoefficientRSRP FilterCoefficient DEFAULT fc4, + filterCoefficientRSRQ FilterCoefficient DEFAULT fc4 +} + +QuantityConfigEUTRA-v1250 ::= SEQUENCE { + filterCoefficientCSI-RSRP-r12 FilterCoefficient OPTIONAL -- Need OR +} + +QuantityConfigEUTRA-v1310 ::= SEQUENCE { + filterCoefficientRS-SINR-r13 FilterCoefficient DEFAULT fc4 +} + +QuantityConfigUTRA ::= SEQUENCE { + measQuantityUTRA-FDD ENUMERATED {cpich-RSCP, cpich-EcN0}, + measQuantityUTRA-TDD ENUMERATED {pccpch-RSCP}, + filterCoefficient FilterCoefficient DEFAULT fc4 +} + +QuantityConfigUTRA-v1020 ::= SEQUENCE { + filterCoefficient2-FDD-r10 FilterCoefficient DEFAULT fc4 +} + +QuantityConfigGERAN ::= SEQUENCE { + measQuantityGERAN ENUMERATED {rssi}, + filterCoefficient FilterCoefficient DEFAULT fc2 +} + +QuantityConfigCDMA2000 ::= SEQUENCE { + measQuantityCDMA2000 ENUMERATED {pilotStrength, pilotPnPhaseAndPilotStrength} +} + +QuantityConfigWLAN-r13 ::= SEQUENCE { + measQuantityWLAN-r13 ENUMERATED {rssiWLAN}, + filterCoefficient-r13 FilterCoefficient DEFAULT fc4 +} + + +ReportConfigEUTRA ::= SEQUENCE { + triggerType CHOICE { + event SEQUENCE { + eventId CHOICE { + eventA1 SEQUENCE { + a1-Threshold ThresholdEUTRA + }, + eventA2 SEQUENCE { + a2-Threshold ThresholdEUTRA + }, + eventA3 SEQUENCE { + a3-Offset INTEGER (-30..30), + reportOnLeave BOOLEAN + }, + eventA4 SEQUENCE { + a4-Threshold ThresholdEUTRA + }, + eventA5 SEQUENCE { + a5-Threshold1 ThresholdEUTRA, + a5-Threshold2 ThresholdEUTRA + }, + ..., + eventA6-r10 SEQUENCE { + a6-Offset-r10 INTEGER (-30..30), + a6-ReportOnLeave-r10 BOOLEAN + }, + eventC1-r12 SEQUENCE { + c1-Threshold-r12 ThresholdEUTRA-v1250, + c1-ReportOnLeave-r12 BOOLEAN + }, + eventC2-r12 SEQUENCE { + c2-RefCSI-RS-r12 MeasCSI-RS-Id-r12, + c2-Offset-r12 INTEGER (-30..30), + c2-ReportOnLeave-r12 BOOLEAN + } + }, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + periodical SEQUENCE { + purpose ENUMERATED { + reportStrongestCells, reportCGI} + } + }, + triggerQuantity ENUMERATED {rsrp, rsrq}, + reportQuantity ENUMERATED {sameAsTriggerQuantity, both}, + maxReportCells INTEGER (1..maxCellReport), + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + ..., + [[ si-RequestForHO-r9 ENUMERATED {setup} OPTIONAL, -- Cond reportCGI + ue-RxTxTimeDiffPeriodical-r9 ENUMERATED {setup} OPTIONAL -- Need OR + ]], + [[ includeLocationInfo-r10 ENUMERATED {true} OPTIONAL, -- Need OR + reportAddNeighMeas-r10 ENUMERATED {setup} OPTIONAL -- Need OR + ]], + [[ alternativeTimeToTrigger-r12 CHOICE { + release NULL, + setup TimeToTrigger + } OPTIONAL, -- Need ON + useT312-r12 BOOLEAN OPTIONAL, -- Need ON + usePSCell-r12 BOOLEAN OPTIONAL, -- Need ON + aN-Threshold1-v1250 RSRQ-RangeConfig-r12 OPTIONAL, -- Need ON + a5-Threshold2-v1250 RSRQ-RangeConfig-r12 OPTIONAL, -- Need ON + reportStrongestCSI-RSs-r12 BOOLEAN OPTIONAL, -- Need ON + reportCRS-Meas-r12 BOOLEAN OPTIONAL, -- Need ON + triggerQuantityCSI-RS-r12 BOOLEAN OPTIONAL -- Need ON + ]], + [[ reportSSTD-Meas-r13 BOOLEAN OPTIONAL, -- Need ON + rs-sinr-Config-r13 CHOICE { + release NULL, + setup SEQUENCE { + triggerQuantity-v1310 ENUMERATED {sinr} OPTIONAL, -- Need ON + aN-Threshold1-r13 RS-SINR-Range-r13 OPTIONAL, -- Need ON + a5-Threshold2-r13 RS-SINR-Range-r13 OPTIONAL, -- Need ON + reportQuantity-v1310 ENUMERATED {rsrpANDsinr, rsrqANDsinr, all} + } + } OPTIONAL, -- Need ON + useWhiteCellList-r13 BOOLEAN OPTIONAL, -- Need ON + measRSSI-ReportConfig-r13 MeasRSSI-ReportConfig-r13 OPTIONAL, -- Need ON + includeMultiBandInfo-r13 ENUMERATED {true} OPTIONAL, -- Cond reportCGI + ul-DelayConfig-r13 UL-DelayConfig-r13 OPTIONAL -- Need ON + ]], + [[ ue-RxTxTimeDiffPeriodicalTDD-r13 BOOLEAN OPTIONAL -- Need ON + ]] +} + +RSRQ-RangeConfig-r12 ::= CHOICE { + release NULL, + setup RSRQ-Range-v1250 +} + +ThresholdEUTRA ::= CHOICE{ + threshold-RSRP RSRP-Range, + threshold-RSRQ RSRQ-Range +} + +ThresholdEUTRA-v1250 ::= CSI-RSRP-Range-r12 + +MeasRSSI-ReportConfig-r13 ::= SEQUENCE { + channelOccupancyThreshold-r13 RSSI-Range-r13 OPTIONAL -- Need OR +} + + +ReportConfigId ::= INTEGER (1..maxReportConfigId) + + +ReportConfigInterRAT ::= SEQUENCE { + triggerType CHOICE { + event SEQUENCE { + eventId CHOICE { + eventB1 SEQUENCE { + b1-Threshold CHOICE { + b1-ThresholdUTRA ThresholdUTRA, + b1-ThresholdGERAN ThresholdGERAN, + b1-ThresholdCDMA2000 ThresholdCDMA2000 + } + }, + eventB2 SEQUENCE { + b2-Threshold1 ThresholdEUTRA, + b2-Threshold2 CHOICE { + b2-Threshold2UTRA ThresholdUTRA, + b2-Threshold2GERAN ThresholdGERAN, + b2-Threshold2CDMA2000 ThresholdCDMA2000 + } + }, + ..., + eventW1-r13 SEQUENCE { + w1-Threshold-r13 WLAN-RSSI-Range-r13 + }, + eventW2-r13 SEQUENCE { + w2-Threshold1-r13 WLAN-RSSI-Range-r13, + w2-Threshold2-r13 WLAN-RSSI-Range-r13 + }, + eventW3-r13 SEQUENCE { + w3-Threshold-r13 WLAN-RSSI-Range-r13 + } + }, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + periodical SEQUENCE { + purpose ENUMERATED { + reportStrongestCells, + reportStrongestCellsForSON, + reportCGI} + } + }, + maxReportCells INTEGER (1..maxCellReport), + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + ..., + [[ si-RequestForHO-r9 ENUMERATED {setup} OPTIONAL -- Cond reportCGI + ]], + [[ reportQuantityUTRA-FDD-r10 ENUMERATED {both} OPTIONAL -- Need OR + ]], + [[ includeLocationInfo-r11 BOOLEAN OPTIONAL -- Need ON + ]], + [[ b2-Threshold1-v1250 CHOICE { + release NULL, + setup RSRQ-Range-v1250 + } OPTIONAL -- Need ON + ]], + [[ reportQuantityWLAN-r13 ReportQuantityWLAN-r13 OPTIONAL -- Need ON + ]] +} + +ThresholdUTRA ::= CHOICE{ + utra-RSCP INTEGER (-5..91), + utra-EcN0 INTEGER (0..49) +} + +ThresholdGERAN ::= INTEGER (0..63) + +ThresholdCDMA2000 ::= INTEGER (0..63) + +ReportQuantityWLAN-r13 ::= SEQUENCE { + bandRequestWLAN-r13 ENUMERATED {true} OPTIONAL, -- Need OR + carrierInfoRequestWLAN-r13 ENUMERATED {true} OPTIONAL, -- Need OR + availableAdmissionCapacityRequestWLAN-r13 ENUMERATED {true} OPTIONAL, -- Need ON + backhaulDL-BandwidthRequestWLAN-r13 ENUMERATED {true} OPTIONAL, -- Need OR + backhaulUL-BandwidthRequestWLAN-r13 ENUMERATED {true} OPTIONAL, -- Need OR + channelUtilizationRequestWLAN-r13 ENUMERATED {true} OPTIONAL, -- Need OR + stationCountRequestWLAN-r13 ENUMERATED {true} OPTIONAL , -- Need OR + ... +} + + +ReportConfigToAddModList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod + +ReportConfigToAddMod ::= SEQUENCE { + reportConfigId ReportConfigId, + reportConfig CHOICE { + reportConfigEUTRA ReportConfigEUTRA, + reportConfigInterRAT ReportConfigInterRAT + } +} + + + +ReportInterval ::= ENUMERATED { + ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240, + min1, min6, min12, min30, min60, spare3, spare2, spare1} + + +RSRP-Range ::= INTEGER(0..97) + +RSRP-RangeSL-r12 ::= INTEGER(0..13) + +RSRP-RangeSL2-r12 ::= INTEGER(0..7) + +RSRP-RangeSL3-r12 ::= INTEGER(0..11) + +RSRP-RangeSL4-r13 ::= INTEGER(0..49) + + +RSRQ-Range ::= INTEGER(0..34) + +RSRQ-Range-v1250 ::= INTEGER(-30..46) + +RSRQ-Range-r13 ::= INTEGER(-30..46) + + +RSRQ-Type-r12 ::= SEQUENCE { + allSymbols-r12 BOOLEAN, + wideBand-r12 BOOLEAN +} + + +RS-SINR-Range-r13 ::= INTEGER(0..127) + + +RSSI-Range-r13 ::= INTEGER(0..76) + + +TimeToTrigger ::= ENUMERATED { + ms0, ms40, ms64, ms80, ms100, ms128, ms160, ms256, + ms320, ms480, ms512, ms640, ms1024, ms1280, ms2560, + ms5120} + + +UL-DelayConfig-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + delayThreshold-r13 ENUMERATED { + ms30, ms40, ms50, ms60, ms70, ms80, + ms90,ms100, ms150, ms300, ms500, ms750, spare4, spare3, spare2, spare1} + } +} + + +WLAN-CarrierInfo-r13 ::= SEQUENCE { + operatingClass-r13 INTEGER (0..255) OPTIONAL, -- Need ON + countryCode-r13 ENUMERATED {unitedStates, europe, japan, global, ...} OPTIONAL, -- Need ON + channelNumbers-r13 WLAN-ChannelList-r13 OPTIONAL, -- Need ON + ... +} + +WLAN-ChannelList-r13 ::= SEQUENCE (SIZE (1..maxWLAN-Channels-r13)) OF WLAN-Channel-r13 + +WLAN-Channel-r13 ::= INTEGER(0..255) + + +WLAN-RSSI-Range-r13 ::= INTEGER(0..141) + + +WLAN-Status-r13 ::= ENUMERATED {successfulAssociation, failureWlanRadioLink, failureWlanUnavailable, failureTimeout} + + +AbsoluteTimeInfo-r10 ::= BIT STRING (SIZE (48)) + + +AreaConfiguration-r10 ::= CHOICE { + cellGlobalIdList-r10 CellGlobalIdList-r10, + trackingAreaCodeList-r10 TrackingAreaCodeList-r10 +} + +AreaConfiguration-v1130 ::= SEQUENCE { + trackingAreaCodeList-v1130 TrackingAreaCodeList-v1130 +} + +CellGlobalIdList-r10 ::= SEQUENCE (SIZE (1..32)) OF CellGlobalIdEUTRA + +TrackingAreaCodeList-r10 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaCode + +TrackingAreaCodeList-v1130 ::= SEQUENCE { + plmn-Identity-perTAC-List-r11 SEQUENCE (SIZE (1..8)) OF PLMN-Identity +} + + +C-RNTI ::= BIT STRING (SIZE (16)) + + +DedicatedInfoCDMA2000 ::= OCTET STRING + + +DedicatedInfoNAS ::= OCTET STRING + + +FilterCoefficient ::= ENUMERATED { + fc0, fc1, fc2, fc3, fc4, fc5, + fc6, fc7, fc8, fc9, fc11, fc13, + fc15, fc17, fc19, spare1, ...} + + +LoggingDuration-r10 ::= ENUMERATED { + min10, min20, min40, min60, min90, min120, spare2, spare1} + + +LoggingInterval-r10 ::= ENUMERATED { + ms1280, ms2560, ms5120, ms10240, ms20480, + ms30720, ms40960, ms61440} + + +MeasSubframePattern-r10 ::= CHOICE { + subframePatternFDD-r10 BIT STRING (SIZE (40)), + subframePatternTDD-r10 CHOICE { + subframeConfig1-5-r10 BIT STRING (SIZE (20)), + subframeConfig0-r10 BIT STRING (SIZE (70)), + subframeConfig6-r10 BIT STRING (SIZE (60)), + ... + }, + ... +} + + +MMEC ::= BIT STRING (SIZE (8)) + + +NeighCellConfig ::= BIT STRING (SIZE (2)) + + +OtherConfig-r9 ::= SEQUENCE { + reportProximityConfig-r9 ReportProximityConfig-r9 OPTIONAL, -- Need ON + ..., + [[ idc-Config-r11 IDC-Config-r11 OPTIONAL, -- Need ON + powerPrefIndicationConfig-r11 PowerPrefIndicationConfig-r11 OPTIONAL, -- Need ON + obtainLocationConfig-r11 ObtainLocationConfig-r11 OPTIONAL -- Need ON + ]] +} + +IDC-Config-r11 ::= SEQUENCE { + idc-Indication-r11 ENUMERATED {setup} OPTIONAL, -- Need OR + autonomousDenialParameters-r11 SEQUENCE { + autonomousDenialSubframes-r11 ENUMERATED {n2, n5, n10, n15, + n20, n30, spare2, spare1}, + autonomousDenialValidity-r11 ENUMERATED { + sf200, sf500, sf1000, sf2000, + spare4, spare3, spare2, spare1} + } OPTIONAL, -- Need OR + ..., + [[ idc-Indication-UL-CA-r11 ENUMERATED {setup} OPTIONAL -- Cond idc-Ind + ]] +} + +ObtainLocationConfig-r11 ::= SEQUENCE { + obtainLocation-r11 ENUMERATED {setup} OPTIONAL -- Need OR +} + +PowerPrefIndicationConfig-r11 ::= CHOICE{ + release NULL, + setup SEQUENCE{ + powerPrefIndicationTimer-r11 ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, + s30, s60, s90, s120, s300, s600, spare3, + spare2, spare1} + } +} + +ReportProximityConfig-r9 ::= SEQUENCE { + proximityIndicationEUTRA-r9 ENUMERATED {enabled} OPTIONAL, -- Need OR + proximityIndicationUTRA-r9 ENUMERATED {enabled} OPTIONAL -- Need OR +} + + +RAND-CDMA2000 ::= BIT STRING (SIZE (32)) + + +RAT-Type ::= ENUMERATED { + eutra, utra, geran-cs, geran-ps, cdma2000-1XRTT, + spare3, spare2, spare1, ...} + + +ResumeIdentity-r13 ::= BIT STRING (SIZE(40)) + + +RRC-TransactionIdentifier ::= INTEGER (0..3) + + +S-TMSI ::= SEQUENCE { + mmec MMEC, + m-TMSI BIT STRING (SIZE (32)) +} + + +TraceReference-r10 ::= SEQUENCE { + plmn-Identity-r10 PLMN-Identity, + traceId-r10 OCTET STRING (SIZE (3)) +} + + +UE-CapabilityRAT-ContainerList ::=SEQUENCE (SIZE (0..maxRAT-Capabilities)) OF UE-CapabilityRAT-Container + +UE-CapabilityRAT-Container ::= SEQUENCE { + rat-Type RAT-Type, + ueCapabilityRAT-Container OCTET STRING +} + + +UE-EUTRA-Capability ::= SEQUENCE { + accessStratumRelease AccessStratumRelease, + ue-Category INTEGER (1..5), + pdcp-Parameters PDCP-Parameters, + phyLayerParameters PhyLayerParameters, + rf-Parameters RF-Parameters, + measParameters MeasParameters, + featureGroupIndicators BIT STRING (SIZE (32)) OPTIONAL, + interRAT-Parameters SEQUENCE { + utraFDD IRAT-ParametersUTRA-FDD OPTIONAL, + utraTDD128 IRAT-ParametersUTRA-TDD128 OPTIONAL, + utraTDD384 IRAT-ParametersUTRA-TDD384 OPTIONAL, + utraTDD768 IRAT-ParametersUTRA-TDD768 OPTIONAL, + geran IRAT-ParametersGERAN OPTIONAL, + cdma2000-HRPD IRAT-ParametersCDMA2000-HRPD OPTIONAL, + cdma2000-1xRTT IRAT-ParametersCDMA2000-1XRTT OPTIONAL + }, + nonCriticalExtension UE-EUTRA-Capability-v920-IEs OPTIONAL +} + +-- Late non critical extensions +UE-EUTRA-Capability-v9a0-IEs ::= SEQUENCE { + featureGroupIndRel9Add-r9 BIT STRING (SIZE (32)) OPTIONAL, + fdd-Add-UE-EUTRA-Capabilities-r9 UE-EUTRA-CapabilityAddXDD-Mode-r9 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-r9 UE-EUTRA-CapabilityAddXDD-Mode-r9 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v9c0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v9c0-IEs ::= SEQUENCE { + interRAT-ParametersUTRA-v9c0 IRAT-ParametersUTRA-v9c0 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v9d0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v9d0-IEs ::= SEQUENCE { + phyLayerParameters-v9d0 PhyLayerParameters-v9d0 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v9e0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v9e0-IEs ::= SEQUENCE { + rf-Parameters-v9e0 RF-Parameters-v9e0 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v9h0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v9h0-IEs ::= SEQUENCE { + interRAT-ParametersUTRA-v9h0 IRAT-ParametersUTRA-v9h0 OPTIONAL, + -- Following field is only to be used for late REL-9 extensions + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v10c0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v10c0-IEs ::= SEQUENCE { + otdoa-PositioningCapabilities-r10 OTDOA-PositioningCapabilities-r10 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v10f0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v10f0-IEs ::= SEQUENCE { + rf-Parameters-v10f0 RF-Parameters-v10f0 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v10i0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v10i0-IEs ::= SEQUENCE { + rf-Parameters-v10i0 RF-Parameters-v10i0 OPTIONAL, + -- Following field is only to be used for late REL-10 extensions + lateNonCriticalExtension OCTET STRING (CONTAINING UE-EUTRA-Capability-v10j0-IEs) OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v11d0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v10j0-IEs ::= SEQUENCE { + rf-Parameters-v10j0 RF-Parameters-v10j0 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-EUTRA-Capability-v11d0-IEs ::= SEQUENCE { + rf-Parameters-v11d0 RF-Parameters-v11d0 OPTIONAL, + otherParameters-v11d0 Other-Parameters-v11d0 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v11x0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v11x0-IEs ::= SEQUENCE { + -- Following field is only to be used for late REL-11 extensions + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v12b0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v12b0-IEs ::= SEQUENCE { + rf-Parameters-v12b0 RF-Parameters-v12b0 OPTIONAL, + -- Following field is only to be used for late REL-12 extensions + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non critical extensions +UE-EUTRA-Capability-v920-IEs ::= SEQUENCE { + phyLayerParameters-v920 PhyLayerParameters-v920, + interRAT-ParametersGERAN-v920 IRAT-ParametersGERAN-v920, + interRAT-ParametersUTRA-v920 IRAT-ParametersUTRA-v920 OPTIONAL, + interRAT-ParametersCDMA2000-v920 IRAT-ParametersCDMA2000-1XRTT-v920 OPTIONAL, + deviceType-r9 ENUMERATED {noBenFromBatConsumpOpt} OPTIONAL, + csg-ProximityIndicationParameters-r9 CSG-ProximityIndicationParameters-r9, + neighCellSI-AcquisitionParameters-r9 NeighCellSI-AcquisitionParameters-r9, + son-Parameters-r9 SON-Parameters-r9, + nonCriticalExtension UE-EUTRA-Capability-v940-IEs OPTIONAL +} + +UE-EUTRA-Capability-v940-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING (CONTAINING UE-EUTRA-Capability-v9a0-IEs) + OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1020-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1020-IEs ::= SEQUENCE { + ue-Category-v1020 INTEGER (6..8) OPTIONAL, + phyLayerParameters-v1020 PhyLayerParameters-v1020 OPTIONAL, + rf-Parameters-v1020 RF-Parameters-v1020 OPTIONAL, + measParameters-v1020 MeasParameters-v1020 OPTIONAL, + featureGroupIndRel10-r10 BIT STRING (SIZE (32)) OPTIONAL, + interRAT-ParametersCDMA2000-v1020 IRAT-ParametersCDMA2000-1XRTT-v1020 OPTIONAL, + ue-BasedNetwPerfMeasParameters-r10 UE-BasedNetwPerfMeasParameters-r10 OPTIONAL, + interRAT-ParametersUTRA-TDD-v1020 IRAT-ParametersUTRA-TDD-v1020 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1060-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1060-IEs ::= SEQUENCE { + fdd-Add-UE-EUTRA-Capabilities-v1060 UE-EUTRA-CapabilityAddXDD-Mode-v1060 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-v1060 UE-EUTRA-CapabilityAddXDD-Mode-v1060 OPTIONAL, + rf-Parameters-v1060 RF-Parameters-v1060 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1090-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1090-IEs ::= SEQUENCE { + rf-Parameters-v1090 RF-Parameters-v1090 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1130-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1130-IEs ::= SEQUENCE { + pdcp-Parameters-v1130 PDCP-Parameters-v1130, + phyLayerParameters-v1130 PhyLayerParameters-v1130 OPTIONAL, + rf-Parameters-v1130 RF-Parameters-v1130, + measParameters-v1130 MeasParameters-v1130, + interRAT-ParametersCDMA2000-v1130 IRAT-ParametersCDMA2000-v1130, + otherParameters-r11 Other-Parameters-r11, + fdd-Add-UE-EUTRA-Capabilities-v1130 UE-EUTRA-CapabilityAddXDD-Mode-v1130 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-v1130 UE-EUTRA-CapabilityAddXDD-Mode-v1130 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1170-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1170-IEs ::= SEQUENCE { + phyLayerParameters-v1170 PhyLayerParameters-v1170 OPTIONAL, + ue-Category-v1170 INTEGER (9..10) OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1180-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1180-IEs ::= SEQUENCE { + rf-Parameters-v1180 RF-Parameters-v1180 OPTIONAL, + mbms-Parameters-r11 MBMS-Parameters-r11 OPTIONAL, + fdd-Add-UE-EUTRA-Capabilities-v1180 UE-EUTRA-CapabilityAddXDD-Mode-v1180 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-v1180 UE-EUTRA-CapabilityAddXDD-Mode-v1180 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v11a0-IEs OPTIONAL +} + +UE-EUTRA-Capability-v11a0-IEs ::= SEQUENCE { + ue-Category-v11a0 INTEGER (11..12) OPTIONAL, + measParameters-v11a0 MeasParameters-v11a0 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1250-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1250-IEs ::= SEQUENCE { + phyLayerParameters-v1250 PhyLayerParameters-v1250 OPTIONAL, + rf-Parameters-v1250 RF-Parameters-v1250 OPTIONAL, + rlc-Parameters-r12 RLC-Parameters-r12 OPTIONAL, + ue-BasedNetwPerfMeasParameters-v1250 UE-BasedNetwPerfMeasParameters-v1250 OPTIONAL, + ue-CategoryDL-r12 INTEGER (0..14) OPTIONAL, + ue-CategoryUL-r12 INTEGER (0..13) OPTIONAL, + wlan-IW-Parameters-r12 WLAN-IW-Parameters-r12 OPTIONAL, + measParameters-v1250 MeasParameters-v1250 OPTIONAL, + dc-Parameters-r12 DC-Parameters-r12 OPTIONAL, + mbms-Parameters-v1250 MBMS-Parameters-v1250 OPTIONAL, + mac-Parameters-r12 MAC-Parameters-r12 OPTIONAL, + fdd-Add-UE-EUTRA-Capabilities-v1250 UE-EUTRA-CapabilityAddXDD-Mode-v1250 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-v1250 UE-EUTRA-CapabilityAddXDD-Mode-v1250 OPTIONAL, + sl-Parameters-r12 SL-Parameters-r12 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1260-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1260-IEs ::= SEQUENCE { + ue-CategoryDL-v1260 INTEGER (15..16) OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1270-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1270-IEs ::= SEQUENCE { + rf-Parameters-v1270 RF-Parameters-v1270 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1280-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1280-IEs ::= SEQUENCE { + phyLayerParameters-v1280 PhyLayerParameters-v1280 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1310-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1310-IEs ::= SEQUENCE { + ue-CategoryDL-v1310 ENUMERATED {n17, m1} OPTIONAL, + ue-CategoryUL-v1310 ENUMERATED {n14, m1} OPTIONAL, + pdcp-Parameters-v1310 PDCP-Parameters-v1310, + rlc-Parameters-v1310 RLC-Parameters-v1310, + mac-Parameters-v1310 MAC-Parameters-v1310 OPTIONAL, + phyLayerParameters-v1310 PhyLayerParameters-v1310 OPTIONAL, + rf-Parameters-v1310 RF-Parameters-v1310 OPTIONAL, + measParameters-v1310 MeasParameters-v1310 OPTIONAL, + dc-Parameters-v1310 DC-Parameters-v1310 OPTIONAL, + sl-Parameters-v1310 SL-Parameters-v1310 OPTIONAL, + scptm-Parameters-r13 SCPTM-Parameters-r13 OPTIONAL, + ce-Parameters-r13 CE-Parameters-r13 OPTIONAL, + interRAT-ParametersWLAN-r13 IRAT-ParametersWLAN-r13, + laa-Parameters-r13 LAA-Parameters-r13 OPTIONAL, + lwa-Parameters-r13 LWA-Parameters-r13 OPTIONAL, + wlan-IW-Parameters-v1310 WLAN-IW-Parameters-v1310, + lwip-Parameters-r13 LWIP-Parameters-r13, + fdd-Add-UE-EUTRA-Capabilities-v1310 UE-EUTRA-CapabilityAddXDD-Mode-v1310 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-v1310 UE-EUTRA-CapabilityAddXDD-Mode-v1310 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1320-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1320-IEs ::= SEQUENCE { + ce-Parameters-v1320 CE-Parameters-v1320 OPTIONAL, + phyLayerParameters-v1320 PhyLayerParameters-v1320 OPTIONAL, + rf-Parameters-v1320 RF-Parameters-v1320 OPTIONAL, + fdd-Add-UE-EUTRA-Capabilities-v1320 UE-EUTRA-CapabilityAddXDD-Mode-v1320 OPTIONAL, + tdd-Add-UE-EUTRA-Capabilities-v1320 UE-EUTRA-CapabilityAddXDD-Mode-v1320 OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1330-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1330-IEs ::= SEQUENCE { + ue-CategoryDL-v1330 INTEGER (18..19) OPTIONAL, + phyLayerParameters-v1330 PhyLayerParameters-v1330 OPTIONAL, + ue-CE-NeedULGaps-r13 ENUMERATED {true} OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v1340-IEs OPTIONAL +} + +UE-EUTRA-Capability-v1340-IEs ::= SEQUENCE { + ue-CategoryUL-v1340 INTEGER (15) OPTIONAL, + nonCriticalExtension UE-EUTRA-Capability-v14xy-IEs OPTIONAL +} + +UE-EUTRA-Capability-v14xy-IEs ::= SEQUENCE { + mac-Parameters-v14xy MAC-Parameters-v14xy OPTIONAL, + rlc-Parameters-v14xy RLC-Parameters-v14xy, + laa-Parameters-v14xy LAA-Parameters-v14xy OPTIONAL, + lwip-Parameters-v14xy LWIP-Parameters-v14xy OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-EUTRA-CapabilityAddXDD-Mode-r9 ::= SEQUENCE { + phyLayerParameters-r9 PhyLayerParameters OPTIONAL, + featureGroupIndicators-r9 BIT STRING (SIZE (32)) OPTIONAL, + featureGroupIndRel9Add-r9 BIT STRING (SIZE (32)) OPTIONAL, + interRAT-ParametersGERAN-r9 IRAT-ParametersGERAN OPTIONAL, + interRAT-ParametersUTRA-r9 IRAT-ParametersUTRA-v920 OPTIONAL, + interRAT-ParametersCDMA2000-r9 IRAT-ParametersCDMA2000-1XRTT-v920 OPTIONAL, + neighCellSI-AcquisitionParameters-r9 NeighCellSI-AcquisitionParameters-r9 OPTIONAL, + ... +} + +UE-EUTRA-CapabilityAddXDD-Mode-v1060 ::= SEQUENCE { + phyLayerParameters-v1060 PhyLayerParameters-v1020 OPTIONAL, + featureGroupIndRel10-v1060 BIT STRING (SIZE (32)) OPTIONAL, + interRAT-ParametersCDMA2000-v1060 IRAT-ParametersCDMA2000-1XRTT-v1020 OPTIONAL, + interRAT-ParametersUTRA-TDD-v1060 IRAT-ParametersUTRA-TDD-v1020 OPTIONAL, + ..., + [[ otdoa-PositioningCapabilities-r10 OTDOA-PositioningCapabilities-r10 OPTIONAL + ]] +} + +UE-EUTRA-CapabilityAddXDD-Mode-v1130 ::= SEQUENCE { + phyLayerParameters-v1130 PhyLayerParameters-v1130 OPTIONAL, + measParameters-v1130 MeasParameters-v1130 OPTIONAL, + otherParameters-r11 Other-Parameters-r11 OPTIONAL, + ... +} + +UE-EUTRA-CapabilityAddXDD-Mode-v1180 ::= SEQUENCE { + mbms-Parameters-r11 MBMS-Parameters-r11 +} + +UE-EUTRA-CapabilityAddXDD-Mode-v1250 ::= SEQUENCE { + phyLayerParameters-v1250 PhyLayerParameters-v1250 OPTIONAL, + measParameters-v1250 MeasParameters-v1250 OPTIONAL +} + +UE-EUTRA-CapabilityAddXDD-Mode-v1310 ::= SEQUENCE { + phyLayerParameters-v1310 PhyLayerParameters-v1310 OPTIONAL +} + +UE-EUTRA-CapabilityAddXDD-Mode-v1320 ::= SEQUENCE { + phyLayerParameters-v1320 PhyLayerParameters-v1320 OPTIONAL, + scptm-Parameters-r13 SCPTM-Parameters-r13 OPTIONAL +} + +AccessStratumRelease ::= ENUMERATED { + rel8, rel9, rel10, rel11, rel12, rel13, + spare2, spare1, ...} + +DC-Parameters-r12 ::= SEQUENCE { + drb-TypeSplit-r12 ENUMERATED {supported} OPTIONAL, + drb-TypeSCG-r12 ENUMERATED {supported} OPTIONAL +} + +DC-Parameters-v1310 ::= SEQUENCE { + pdcp-TransferSplitUL-r13 ENUMERATED {supported} OPTIONAL, + ue-SSTD-Meas-r13 ENUMERATED {supported} OPTIONAL +} + +MAC-Parameters-r12 ::= SEQUENCE { + logicalChannelSR-ProhibitTimer-r12 ENUMERATED {supported} OPTIONAL, + longDRX-Command-r12 ENUMERATED {supported} OPTIONAL +} + +MAC-Parameters-v1310 ::= SEQUENCE { + extendedMAC-LengthField-r13 ENUMERATED {supported} OPTIONAL, + extendedLongDRX-r13 ENUMERATED {supported} OPTIONAL +} + +MAC-Parameters-v14xy ::= SEQUENCE { + shortSPS-IntervalFDD-r14 ENUMERATED {supported} OPTIONAL, + shortSPS-IntervalTDD-r14 ENUMERATED {supported} OPTIONAL, + skipUplinkDynamic-r14 ENUMERATED {supported} OPTIONAL, + skipUplinkSPS-r14 ENUMERATED {supported} OPTIONAL +} + +RLC-Parameters-r12 ::= SEQUENCE { + extended-RLC-LI-Field-r12 ENUMERATED {supported} +} + +RLC-Parameters-v1310 ::= SEQUENCE { + extendedRLC-SN-SO-Field-r13 ENUMERATED {supported} OPTIONAL +} + +RLC-Parameters-v14xy ::= SEQUENCE { + extendedPollByte-r14 ENUMERATED {supported} OPTIONAL +} + +PDCP-Parameters ::= SEQUENCE { + supportedROHC-Profiles SEQUENCE { + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + maxNumberROHC-ContextSessions ENUMERATED { + cs2, cs4, cs8, cs12, cs16, cs24, cs32, + cs48, cs64, cs128, cs256, cs512, cs1024, + cs16384, spare2, spare1} DEFAULT cs16, + ... +} + +PDCP-Parameters-v1130 ::= SEQUENCE { + pdcp-SN-Extension-r11 ENUMERATED {supported} OPTIONAL, + supportRohcContextContinue-r11 ENUMERATED {supported} OPTIONAL +} + +PDCP-Parameters-v1310 ::= SEQUENCE { + pdcp-SN-Extension-18bits-r13 ENUMERATED {supported} OPTIONAL +} + +PhyLayerParameters ::= SEQUENCE { + ue-TxAntennaSelectionSupported BOOLEAN, + ue-SpecificRefSigsSupported BOOLEAN +} + +PhyLayerParameters-v920 ::= SEQUENCE { + enhancedDualLayerFDD-r9 ENUMERATED {supported} OPTIONAL, + enhancedDualLayerTDD-r9 ENUMERATED {supported} OPTIONAL +} + +PhyLayerParameters-v9d0 ::= SEQUENCE { + tm5-FDD-r9 ENUMERATED {supported} OPTIONAL, + tm5-TDD-r9 ENUMERATED {supported} OPTIONAL +} + +PhyLayerParameters-v1020 ::= SEQUENCE { + twoAntennaPortsForPUCCH-r10 ENUMERATED {supported} OPTIONAL, + tm9-With-8Tx-FDD-r10 ENUMERATED {supported} OPTIONAL, + pmi-Disabling-r10 ENUMERATED {supported} OPTIONAL, + crossCarrierScheduling-r10 ENUMERATED {supported} OPTIONAL, + simultaneousPUCCH-PUSCH-r10 ENUMERATED {supported} OPTIONAL, + multiClusterPUSCH-WithinCC-r10 ENUMERATED {supported} OPTIONAL, + nonContiguousUL-RA-WithinCC-List-r10 NonContiguousUL-RA-WithinCC-List-r10 OPTIONAL +} + +PhyLayerParameters-v1130 ::= SEQUENCE { + crs-InterfHandl-r11 ENUMERATED {supported} OPTIONAL, + ePDCCH-r11 ENUMERATED {supported} OPTIONAL, + multiACK-CSI-Reporting-r11 ENUMERATED {supported} OPTIONAL, + ss-CCH-InterfHandl-r11 ENUMERATED {supported} OPTIONAL, + tdd-SpecialSubframe-r11 ENUMERATED {supported} OPTIONAL, + txDiv-PUCCH1b-ChSelect-r11 ENUMERATED {supported} OPTIONAL, + ul-CoMP-r11 ENUMERATED {supported} OPTIONAL +} + +PhyLayerParameters-v1170 ::= SEQUENCE { + interBandTDD-CA-WithDifferentConfig-r11 BIT STRING (SIZE (2)) OPTIONAL +} + +PhyLayerParameters-v1250 ::= SEQUENCE { + e-HARQ-Pattern-FDD-r12 ENUMERATED {supported} OPTIONAL, + enhanced-4TxCodebook-r12 ENUMERATED {supported} OPTIONAL, + tdd-FDD-CA-PCellDuplex-r12 BIT STRING (SIZE (2)) OPTIONAL, + phy-TDD-ReConfig-TDD-PCell-r12 ENUMERATED {supported} OPTIONAL, + phy-TDD-ReConfig-FDD-PCell-r12 ENUMERATED {supported} OPTIONAL, + pusch-FeedbackMode-r12 ENUMERATED {supported} OPTIONAL, + pusch-SRS-PowerControl-SubframeSet-r12 ENUMERATED {supported} OPTIONAL, + csi-SubframeSet-r12 ENUMERATED {supported} OPTIONAL, + noResourceRestrictionForTTIBundling-r12 ENUMERATED {supported} OPTIONAL, + discoverySignalsInDeactSCell-r12 ENUMERATED {supported} OPTIONAL, + naics-Capability-List-r12 NAICS-Capability-List-r12 OPTIONAL +} + +PhyLayerParameters-v1280 ::= SEQUENCE { + alternativeTBS-Indices-r12 ENUMERATED {supported} OPTIONAL +} + +PhyLayerParameters-v1310 ::= SEQUENCE { + aperiodicCSI-Reporting-r13 BIT STRING (SIZE (2)) OPTIONAL, + codebook-HARQ-ACK-r13 BIT STRING (SIZE (2)) OPTIONAL, + crossCarrierScheduling-B5C-r13 ENUMERATED {supported} OPTIONAL, + fdd-HARQ-TimingTDD-r13 ENUMERATED {supported} OPTIONAL, maxNumberUpdatedCSI-Proc-r13 INTEGER(5..32) OPTIONAL, + pucch-Format4-r13 ENUMERATED {supported} OPTIONAL, + pucch-Format5-r13 ENUMERATED {supported} OPTIONAL, + pucch-SCell-r13 ENUMERATED {supported} OPTIONAL, + spatialBundling-HARQ-ACK-r13 ENUMERATED {supported} OPTIONAL, + supportedBlindDecoding-r13 SEQUENCE { + maxNumberDecoding-r13 INTEGER(1..32) OPTIONAL, + pdcch-CandidateReductions-r13 ENUMERATED {supported} OPTIONAL, + skipMonitoringDCI-Format0-1A-r13 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + uci-PUSCH-Ext-r13 ENUMERATED {supported} OPTIONAL, + crs-InterfMitigationTM10-r13 ENUMERATED {supported} OPTIONAL, + pdsch-CollisionHandling-r13 ENUMERATED {supported} OPTIONAL +} + +PhyLayerParameters-v1320 ::= SEQUENCE { + mimo-UE-Parameters-r13 MIMO-UE-Parameters-r13 OPTIONAL +} + +PhyLayerParameters-v1330 ::= SEQUENCE { + cch-InterfMitigation-RefRecTypeA-r13 ENUMERATED {supported} OPTIONAL, + cch-InterfMitigation-RefRecTypeB-r13 ENUMERATED {supported} OPTIONAL, + cch-InterfMitigation-MaxNumCCs-r13 INTEGER (1.. maxServCell-r13) OPTIONAL, + crs-InterfMitigationTM1toTM9-r13 INTEGER (1.. maxServCell-r13) OPTIONAL +} + +MIMO-UE-Parameters-r13 ::= SEQUENCE { + parametersTM9-r13 MIMO-UE-ParametersPerTM-r13 OPTIONAL, + parametersTM10-r13 MIMO-UE-ParametersPerTM-r13 OPTIONAL, + srs-EnhancementsTDD-r13 ENUMERATED {supported} OPTIONAL, + srs-Enhancements-r13 ENUMERATED {supported} OPTIONAL, + interferenceMeasRestriction-r13 ENUMERATED {supported} OPTIONAL +} + +MIMO-UE-ParametersPerTM-r13 ::= SEQUENCE { + nonPrecoded-r13 MIMO-NonPrecodedCapabilities-r13 OPTIONAL, + beamformed-r13 MIMO-UE-BeamformedCapabilities-r13 OPTIONAL, + channelMeasRestriction-r13 ENUMERATED {supported} OPTIONAL, + dmrs-Enhancements-r13 ENUMERATED {supported} OPTIONAL, + csi-RS-EnhancementsTDD-r13 ENUMERATED {supported} OPTIONAL +} + +MIMO-CA-ParametersPerBoBC-r13 ::= SEQUENCE { + parametersTM9-r13 MIMO-CA-ParametersPerBoBCPerTM-r13 OPTIONAL, + parametersTM10-r13 MIMO-CA-ParametersPerBoBCPerTM-r13 OPTIONAL +} + +MIMO-CA-ParametersPerBoBCPerTM-r13 ::= SEQUENCE { + nonPrecoded-r13 MIMO-NonPrecodedCapabilities-r13 OPTIONAL, + beamformed-r13 MIMO-BeamformedCapabilityList-r13 OPTIONAL, + dmrs-Enhancements-r13 ENUMERATED {different} OPTIONAL +} + +MIMO-NonPrecodedCapabilities-r13 ::= SEQUENCE { + config1-r13 ENUMERATED {supported} OPTIONAL, + config2-r13 ENUMERATED {supported} OPTIONAL, + config3-r13 ENUMERATED {supported} OPTIONAL, + config4-r13 ENUMERATED {supported} OPTIONAL +} + +MIMO-UE-BeamformedCapabilities-r13 ::= SEQUENCE { + altCodebook-r13 ENUMERATED {supported} OPTIONAL, + mimo-BeamformedCapabilities-r13 MIMO-BeamformedCapabilityList-r13 +} + +MIMO-BeamformedCapabilityList-r13 ::= SEQUENCE (SIZE (1..maxCSI-Proc-r11)) OF MIMO-BeamformedCapabilities-r13 + +MIMO-BeamformedCapabilities-r13 ::= SEQUENCE { + k-Max-r13 INTEGER (1..8), + n-MaxList-r13 BIT STRING (SIZE (1..7)) OPTIONAL + } + +NonContiguousUL-RA-WithinCC-List-r10 ::= SEQUENCE (SIZE (1..maxBands)) OF NonContiguousUL-RA-WithinCC-r10 + +NonContiguousUL-RA-WithinCC-r10 ::= SEQUENCE { + nonContiguousUL-RA-WithinCC-Info-r10 ENUMERATED {supported} OPTIONAL +} + +RF-Parameters ::= SEQUENCE { + supportedBandListEUTRA SupportedBandListEUTRA +} + +RF-Parameters-v9e0 ::= SEQUENCE { + supportedBandListEUTRA-v9e0 SupportedBandListEUTRA-v9e0 OPTIONAL +} + +RF-Parameters-v1020 ::= SEQUENCE { + supportedBandCombination-r10 SupportedBandCombination-r10 +} + +RF-Parameters-v1060 ::= SEQUENCE { + supportedBandCombinationExt-r10 SupportedBandCombinationExt-r10 +} + +RF-Parameters-v1090 ::= SEQUENCE { + supportedBandCombination-v1090 SupportedBandCombination-v1090 OPTIONAL +} + +RF-Parameters-v10f0 ::= SEQUENCE { + modifiedMPR-Behavior-r10 BIT STRING (SIZE (32)) OPTIONAL +} + +RF-Parameters-v10i0 ::= SEQUENCE { + supportedBandCombination-v10i0 SupportedBandCombination-v10i0 OPTIONAL +} + +RF-Parameters-v10j0 ::= SEQUENCE { + multiNS-Pmax-r10 ENUMERATED {supported} OPTIONAL +} + +RF-Parameters-v1130 ::= SEQUENCE { + supportedBandCombination-v1130 SupportedBandCombination-v1130 OPTIONAL +} + +RF-Parameters-v1180 ::= SEQUENCE { + freqBandRetrieval-r11 ENUMERATED {supported} OPTIONAL, + requestedBands-r11 SEQUENCE (SIZE (1.. maxBands)) OF FreqBandIndicator-r11 OPTIONAL, + supportedBandCombinationAdd-r11 SupportedBandCombinationAdd-r11 OPTIONAL +} + +RF-Parameters-v11d0 ::= SEQUENCE { + supportedBandCombinationAdd-v11d0 SupportedBandCombinationAdd-v11d0 OPTIONAL +} + +RF-Parameters-v1250 ::= SEQUENCE { + supportedBandListEUTRA-v1250 SupportedBandListEUTRA-v1250 OPTIONAL, + supportedBandCombination-v1250 SupportedBandCombination-v1250 OPTIONAL, + supportedBandCombinationAdd-v1250 SupportedBandCombinationAdd-v1250 OPTIONAL, + freqBandPriorityAdjustment-r12 ENUMERATED {supported} OPTIONAL +} + +RF-Parameters-v1270 ::= SEQUENCE { + supportedBandCombination-v1270 SupportedBandCombination-v1270 OPTIONAL, + supportedBandCombinationAdd-v1270 SupportedBandCombinationAdd-v1270 OPTIONAL +} + +RF-Parameters-v1310 ::= SEQUENCE { + eNB-RequestedParameters-r13 SEQUENCE { + reducedIntNonContCombRequested-r13 ENUMERATED {true} OPTIONAL, + requestedCCsDL-r13 INTEGER (2..32) OPTIONAL, + requestedCCsUL-r13 INTEGER (2..32) OPTIONAL, + skipFallbackCombRequested-r13 ENUMERATED {true} OPTIONAL + } OPTIONAL, + maximumCCsRetrieval-r13 ENUMERATED {supported} OPTIONAL, + skipFallbackCombinations-r13 ENUMERATED {supported} OPTIONAL, + reducedIntNonContComb-r13 ENUMERATED {supported} OPTIONAL, + supportedBandListEUTRA-v1310 SupportedBandListEUTRA-v1310 OPTIONAL, + supportedBandCombinationReduced-r13 SupportedBandCombinationReduced-r13 OPTIONAL +} + +RF-Parameters-v1320 ::= SEQUENCE { + supportedBandListEUTRA-v1320 SupportedBandListEUTRA-v1320 OPTIONAL, + supportedBandCombination-v1320 SupportedBandCombination-v1320 OPTIONAL, + supportedBandCombinationAdd-v1320 SupportedBandCombinationAdd-v1320 OPTIONAL, + supportedBandCombinationReduced-v1320 SupportedBandCombinationReduced-v1320 OPTIONAL +} + +RF-Parameters-v12b0 ::= SEQUENCE { + maxLayersMIMO-Indication-r12 ENUMERATED {supported} OPTIONAL +} + +SupportedBandCombination-r10 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-r10 + +SupportedBandCombinationExt-r10 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParametersExt-r10 + +SupportedBandCombination-v1090 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-v1090 + +SupportedBandCombination-v10i0 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-v10i0 + +SupportedBandCombination-v1130 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-v1130 + +SupportedBandCombination-v1250 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-v1250 + +SupportedBandCombination-v1270 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-v1270 + +SupportedBandCombination-v1320 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandCombinationParameters-v1320 + +SupportedBandCombinationAdd-r11 ::= SEQUENCE (SIZE (1..maxBandComb-r11)) OF BandCombinationParameters-r11 + +SupportedBandCombinationAdd-v11d0 ::= SEQUENCE (SIZE (1..maxBandComb-r11)) OF BandCombinationParameters-v10i0 + +SupportedBandCombinationAdd-v1250 ::= SEQUENCE (SIZE (1..maxBandComb-r11)) OF BandCombinationParameters-v1250 + +SupportedBandCombinationAdd-v1270 ::= SEQUENCE (SIZE (1..maxBandComb-r11)) OF BandCombinationParameters-v1270 + +SupportedBandCombinationAdd-v1320 ::= SEQUENCE (SIZE (1..maxBandComb-r11)) OF BandCombinationParameters-v1320 + +SupportedBandCombinationReduced-r13 ::= SEQUENCE (SIZE (1..maxBandComb-r13)) OF BandCombinationParameters-r13 + +SupportedBandCombinationReduced-v1320 ::= SEQUENCE (SIZE (1..maxBandComb-r13)) OF BandCombinationParameters-v1320 + +BandCombinationParameters-r10 ::= SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF BandParameters-r10 + +BandCombinationParametersExt-r10 ::= SEQUENCE { + supportedBandwidthCombinationSet-r10 SupportedBandwidthCombinationSet-r10 OPTIONAL +} + +BandCombinationParameters-v1090 ::= SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF BandParameters-v1090 + +BandCombinationParameters-v10i0::= SEQUENCE { +bandParameterList-v10i0 SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF + BandParameters-v10i0 OPTIONAL +} + +BandCombinationParameters-v1130 ::= SEQUENCE { + multipleTimingAdvance-r11 ENUMERATED {supported} OPTIONAL, + simultaneousRx-Tx-r11 ENUMERATED {supported} OPTIONAL, + bandParameterList-r11 SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF BandParameters-v1130 OPTIONAL, + ... +} + +BandCombinationParameters-r11 ::= SEQUENCE { + bandParameterList-r11 SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF + BandParameters-r11, + supportedBandwidthCombinationSet-r11 SupportedBandwidthCombinationSet-r10 OPTIONAL, + multipleTimingAdvance-r11 ENUMERATED {supported} OPTIONAL, + simultaneousRx-Tx-r11 ENUMERATED {supported} OPTIONAL, + bandInfoEUTRA-r11 BandInfoEUTRA, + ... +} + +BandCombinationParameters-v1250::= SEQUENCE { + dc-Support-r12 SEQUENCE { + asynchronous-r12 ENUMERATED {supported} OPTIONAL, + supportedCellGrouping-r12 CHOICE { + threeEntries-r12 BIT STRING (SIZE(3)), + fourEntries-r12 BIT STRING (SIZE(7)), + fiveEntries-r12 BIT STRING (SIZE(15)) + } OPTIONAL + } OPTIONAL, + supportedNAICS-2CRS-AP-r12 BIT STRING (SIZE (1..maxNAICS-Entries-r12)) OPTIONAL, + commSupportedBandsPerBC-r12 BIT STRING (SIZE (1.. maxBands)) OPTIONAL, + ... +} + +BandCombinationParameters-v1270 ::= SEQUENCE { + bandParameterList-v1270 SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF + BandParameters-v1270 OPTIONAL +} + +BandCombinationParameters-r13 ::= SEQUENCE { + differentFallbackSupported-r13 ENUMERATED {true} OPTIONAL, + bandParameterList-r13 SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF BandParameters-r13, + supportedBandwidthCombinationSet-r13 SupportedBandwidthCombinationSet-r10 OPTIONAL, + multipleTimingAdvance-r13 ENUMERATED {supported} OPTIONAL, + simultaneousRx-Tx-r13 ENUMERATED {supported} OPTIONAL, + bandInfoEUTRA-r13 BandInfoEUTRA, + dc-Support-r13 SEQUENCE { + asynchronous-r13 ENUMERATED {supported} OPTIONAL, + supportedCellGrouping-r13 CHOICE { + threeEntries-r13 BIT STRING (SIZE(3)), + fourEntries-r13 BIT STRING (SIZE(7)), + fiveEntries-r13 BIT STRING (SIZE(15)) + } OPTIONAL + } OPTIONAL, + supportedNAICS-2CRS-AP-r13 BIT STRING (SIZE (1..maxNAICS-Entries-r12)) OPTIONAL, + commSupportedBandsPerBC-r13 BIT STRING (SIZE (1.. maxBands)) OPTIONAL +} + +BandCombinationParameters-v1320 ::= SEQUENCE { + bandParameterList-v1320 SEQUENCE (SIZE (1..maxSimultaneousBands-r10)) OF + BandParameters-v1320 OPTIONAL, + additionalRx-Tx-PerformanceReq-r13 ENUMERATED {supported} OPTIONAL +} + +SupportedBandwidthCombinationSet-r10 ::= BIT STRING (SIZE (1..maxBandwidthCombSet-r10)) + +BandParameters-r10 ::= SEQUENCE { + bandEUTRA-r10 FreqBandIndicator, + bandParametersUL-r10 BandParametersUL-r10 OPTIONAL, + bandParametersDL-r10 BandParametersDL-r10 OPTIONAL +} + +BandParameters-v1090 ::= SEQUENCE { + bandEUTRA-v1090 FreqBandIndicator-v9e0 OPTIONAL, + ... +} + +BandParameters-v10i0::= SEQUENCE { + bandParametersDL-v10i0 SEQUENCE (SIZE (1..maxBandwidthClass-r10)) OF CA-MIMO-ParametersDL-v10i0 +} + +BandParameters-v1130 ::= SEQUENCE { + supportedCSI-Proc-r11 ENUMERATED {n1, n3, n4} +} + +BandParameters-r11 ::= SEQUENCE { + bandEUTRA-r11 FreqBandIndicator-r11, + bandParametersUL-r11 BandParametersUL-r10 OPTIONAL, + bandParametersDL-r11 BandParametersDL-r10 OPTIONAL, + supportedCSI-Proc-r11 ENUMERATED {n1, n3, n4} OPTIONAL +} + +BandParameters-v1270 ::= SEQUENCE { + bandParametersDL-v1270 SEQUENCE (SIZE (1..maxBandwidthClass-r10)) OF CA-MIMO-ParametersDL-v1270 +} + +BandParameters-r13 ::= SEQUENCE { + bandEUTRA-r13 FreqBandIndicator-r11, + bandParametersUL-r13 BandParametersUL-r13 OPTIONAL, + bandParametersDL-r13 BandParametersDL-r13 OPTIONAL, + supportedCSI-Proc-r13 ENUMERATED {n1, n3, n4} OPTIONAL +} + +BandParameters-v1320 ::= SEQUENCE { + bandParametersDL-v1320 MIMO-CA-ParametersPerBoBC-r13 +} + +BandParametersUL-r10 ::= SEQUENCE (SIZE (1..maxBandwidthClass-r10)) OF CA-MIMO-ParametersUL-r10 + +BandParametersUL-r13 ::= CA-MIMO-ParametersUL-r10 + + +CA-MIMO-ParametersUL-r10 ::= SEQUENCE { + ca-BandwidthClassUL-r10 CA-BandwidthClass-r10, + supportedMIMO-CapabilityUL-r10 MIMO-CapabilityUL-r10 OPTIONAL +} + +BandParametersDL-r10 ::= SEQUENCE (SIZE (1..maxBandwidthClass-r10)) OF CA-MIMO-ParametersDL-r10 + +BandParametersDL-r13 ::= CA-MIMO-ParametersDL-r13 + +CA-MIMO-ParametersDL-r10 ::= SEQUENCE { + ca-BandwidthClassDL-r10 CA-BandwidthClass-r10, + supportedMIMO-CapabilityDL-r10 MIMO-CapabilityDL-r10 OPTIONAL +} + +CA-MIMO-ParametersDL-v10i0 ::= SEQUENCE { + fourLayerTM3-TM4-r10 ENUMERATED {supported} OPTIONAL +} + +CA-MIMO-ParametersDL-v1270 ::= SEQUENCE { + intraBandContiguousCC-InfoList-r12 SEQUENCE (SIZE (1..maxServCell-r10)) OF IntraBandContiguousCC-Info-r12 +} + +CA-MIMO-ParametersDL-r13 ::= SEQUENCE { + ca-BandwidthClassDL-r13 CA-BandwidthClass-r10, + supportedMIMO-CapabilityDL-r13 MIMO-CapabilityDL-r10 OPTIONAL, + fourLayerTM3-TM4-r13 ENUMERATED {supported} OPTIONAL, + intraBandContiguousCC-InfoList-r13 SEQUENCE (SIZE (1..maxServCell-r13)) OF IntraBandContiguousCC-Info-r12 +} + +IntraBandContiguousCC-Info-r12 ::= SEQUENCE { + fourLayerTM3-TM4-perCC-r12 ENUMERATED {supported} OPTIONAL, + supportedMIMO-CapabilityDL-r12 MIMO-CapabilityDL-r10 OPTIONAL, + supportedCSI-Proc-r12 ENUMERATED {n1, n3, n4} OPTIONAL +} + +CA-BandwidthClass-r10 ::= ENUMERATED {a, b, c, d, e, f, ...} + +MIMO-CapabilityUL-r10 ::= ENUMERATED {twoLayers, fourLayers} + +MIMO-CapabilityDL-r10 ::= ENUMERATED {twoLayers, fourLayers, eightLayers} + +SupportedBandListEUTRA ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA + +SupportedBandListEUTRA-v9e0::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA-v9e0 + +SupportedBandListEUTRA-v1250 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA-v1250 + +SupportedBandListEUTRA-v1310 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA-v1310 + +SupportedBandListEUTRA-v1320 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandEUTRA-v1320 + +SupportedBandEUTRA ::= SEQUENCE { + bandEUTRA FreqBandIndicator, + halfDuplex BOOLEAN +} + +SupportedBandEUTRA-v9e0 ::= SEQUENCE { + bandEUTRA-v9e0 FreqBandIndicator-v9e0 OPTIONAL +} + +SupportedBandEUTRA-v1250 ::= SEQUENCE { + dl-256QAM-r12 ENUMERATED {supported} OPTIONAL, + ul-64QAM-r12 ENUMERATED {supported} OPTIONAL +} + +SupportedBandEUTRA-v1310 ::= SEQUENCE { + ue-PowerClass-5-r13 ENUMERATED {supported} OPTIONAL +} +SupportedBandEUTRA-v1320 ::= SEQUENCE { + intraFreq-CE-NeedForGaps-r13 ENUMERATED {supported} OPTIONAL, + ue-PowerClass-N-r13 ENUMERATED {class1, class2, class4} OPTIONAL +} + +MeasParameters ::= SEQUENCE { + bandListEUTRA BandListEUTRA +} + +MeasParameters-v1020 ::= SEQUENCE { + bandCombinationListEUTRA-r10 BandCombinationListEUTRA-r10 +} + +MeasParameters-v1130 ::= SEQUENCE { + rsrqMeasWideband-r11 ENUMERATED {supported} OPTIONAL +} + +MeasParameters-v11a0 ::= SEQUENCE { + benefitsFromInterruption-r11 ENUMERATED {true} OPTIONAL +} + +MeasParameters-v1250 ::= SEQUENCE { + timerT312-r12 ENUMERATED {supported} OPTIONAL, + alternativeTimeToTrigger-r12 ENUMERATED {supported} OPTIONAL, + incMonEUTRA-r12 ENUMERATED {supported} OPTIONAL, + incMonUTRA-r12 ENUMERATED {supported} OPTIONAL, + extendedMaxMeasId-r12 ENUMERATED {supported} OPTIONAL, + extendedRSRQ-LowerRange-r12 ENUMERATED {supported} OPTIONAL, + rsrq-OnAllSymbols-r12 ENUMERATED {supported} OPTIONAL, + crs-DiscoverySignalsMeas-r12 ENUMERATED {supported} OPTIONAL, + csi-RS-DiscoverySignalsMeas-r12 ENUMERATED {supported} OPTIONAL +} + +MeasParameters-v1310 ::= SEQUENCE { + rs-SINR-Meas-r13 ENUMERATED {supported} OPTIONAL, + whiteCellList-r13 ENUMERATED {supported} OPTIONAL, + extendedMaxObjectId-r13 ENUMERATED {supported} OPTIONAL, + ul-PDCP-Delay-r13 ENUMERATED {supported} OPTIONAL, + extendedFreqPriorities-r13 ENUMERATED {supported} OPTIONAL, + multiBandInfoReport-r13 ENUMERATED {supported} OPTIONAL, + rssi-AndChannelOccupancyReporting-r13 ENUMERATED {supported} OPTIONAL +} + +BandListEUTRA ::= SEQUENCE (SIZE (1..maxBands)) OF BandInfoEUTRA + +BandCombinationListEUTRA-r10 ::= SEQUENCE (SIZE (1..maxBandComb-r10)) OF BandInfoEUTRA + +BandInfoEUTRA ::= SEQUENCE { + interFreqBandList InterFreqBandList, + interRAT-BandList InterRAT-BandList OPTIONAL +} + +InterFreqBandList ::= SEQUENCE (SIZE (1..maxBands)) OF InterFreqBandInfo + +InterFreqBandInfo ::= SEQUENCE { + interFreqNeedForGaps BOOLEAN +} + +InterRAT-BandList ::= SEQUENCE (SIZE (1..maxBands)) OF InterRAT-BandInfo + +InterRAT-BandInfo ::= SEQUENCE { + interRAT-NeedForGaps BOOLEAN +} + +IRAT-ParametersUTRA-FDD ::= SEQUENCE { + supportedBandListUTRA-FDD SupportedBandListUTRA-FDD +} + +IRAT-ParametersUTRA-v920 ::= SEQUENCE { + e-RedirectionUTRA-r9 ENUMERATED {supported} +} + +IRAT-ParametersUTRA-v9c0 ::= SEQUENCE { + voiceOverPS-HS-UTRA-FDD-r9 ENUMERATED {supported} OPTIONAL, + voiceOverPS-HS-UTRA-TDD128-r9 ENUMERATED {supported} OPTIONAL, + srvcc-FromUTRA-FDD-ToUTRA-FDD-r9 ENUMERATED {supported} OPTIONAL, + srvcc-FromUTRA-FDD-ToGERAN-r9 ENUMERATED {supported} OPTIONAL, + srvcc-FromUTRA-TDD128-ToUTRA-TDD128-r9 ENUMERATED {supported} OPTIONAL, + srvcc-FromUTRA-TDD128-ToGERAN-r9 ENUMERATED {supported} OPTIONAL +} + +IRAT-ParametersUTRA-v9h0 ::= SEQUENCE { + mfbi-UTRA-r9 ENUMERATED {supported} +} + +SupportedBandListUTRA-FDD ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-FDD + +SupportedBandUTRA-FDD ::= ENUMERATED { + bandI, bandII, bandIII, bandIV, bandV, bandVI, + bandVII, bandVIII, bandIX, bandX, bandXI, + bandXII, bandXIII, bandXIV, bandXV, bandXVI, ..., + bandXVII-8a0, bandXVIII-8a0, bandXIX-8a0, bandXX-8a0, + bandXXI-8a0, bandXXII-8a0, bandXXIII-8a0, bandXXIV-8a0, + bandXXV-8a0, bandXXVI-8a0, bandXXVII-8a0, bandXXVIII-8a0, + bandXXIX-8a0, bandXXX-8a0, bandXXXI-8a0, bandXXXII-8a0} + +IRAT-ParametersUTRA-TDD128 ::= SEQUENCE { + supportedBandListUTRA-TDD128 SupportedBandListUTRA-TDD128 +} + +SupportedBandListUTRA-TDD128 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD128 + +SupportedBandUTRA-TDD128 ::= ENUMERATED { + a, b, c, d, e, f, g, h, i, j, k, l, m, n, + o, p, ...} + +IRAT-ParametersUTRA-TDD384 ::= SEQUENCE { + supportedBandListUTRA-TDD384 SupportedBandListUTRA-TDD384 +} + +SupportedBandListUTRA-TDD384 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD384 + +SupportedBandUTRA-TDD384 ::= ENUMERATED { + a, b, c, d, e, f, g, h, i, j, k, l, m, n, + o, p, ...} + +IRAT-ParametersUTRA-TDD768 ::= SEQUENCE { + supportedBandListUTRA-TDD768 SupportedBandListUTRA-TDD768 +} + +SupportedBandListUTRA-TDD768 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandUTRA-TDD768 + +SupportedBandUTRA-TDD768 ::= ENUMERATED { + a, b, c, d, e, f, g, h, i, j, k, l, m, n, + o, p, ...} + +IRAT-ParametersUTRA-TDD-v1020 ::= SEQUENCE { + e-RedirectionUTRA-TDD-r10 ENUMERATED {supported} +} + +IRAT-ParametersGERAN ::= SEQUENCE { + supportedBandListGERAN SupportedBandListGERAN, + interRAT-PS-HO-ToGERAN BOOLEAN +} + +IRAT-ParametersGERAN-v920 ::= SEQUENCE { + dtm-r9 ENUMERATED {supported} OPTIONAL, + e-RedirectionGERAN-r9 ENUMERATED {supported} OPTIONAL +} + +SupportedBandListGERAN ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandGERAN + +SupportedBandGERAN ::= ENUMERATED { + gsm450, gsm480, gsm710, gsm750, gsm810, gsm850, + gsm900P, gsm900E, gsm900R, gsm1800, gsm1900, + spare5, spare4, spare3, spare2, spare1, ...} + +IRAT-ParametersCDMA2000-HRPD ::= SEQUENCE { + supportedBandListHRPD SupportedBandListHRPD, + tx-ConfigHRPD ENUMERATED {single, dual}, + rx-ConfigHRPD ENUMERATED {single, dual} +} + +SupportedBandListHRPD ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandclassCDMA2000 + +IRAT-ParametersCDMA2000-1XRTT ::= SEQUENCE { + supportedBandList1XRTT SupportedBandList1XRTT, + tx-Config1XRTT ENUMERATED {single, dual}, + rx-Config1XRTT ENUMERATED {single, dual} +} + +IRAT-ParametersCDMA2000-1XRTT-v920 ::= SEQUENCE { + e-CSFB-1XRTT-r9 ENUMERATED {supported}, + e-CSFB-ConcPS-Mob1XRTT-r9 ENUMERATED {supported} OPTIONAL +} + +IRAT-ParametersCDMA2000-1XRTT-v1020 ::= SEQUENCE { + e-CSFB-dual-1XRTT-r10 ENUMERATED {supported} +} + +IRAT-ParametersCDMA2000-v1130 ::= SEQUENCE { + cdma2000-NW-Sharing-r11 ENUMERATED {supported} OPTIONAL +} + +SupportedBandList1XRTT ::= SEQUENCE (SIZE (1..maxCDMA-BandClass)) OF BandclassCDMA2000 + +IRAT-ParametersWLAN-r13 ::= SEQUENCE { + supportedBandListWLAN-r13 SEQUENCE (SIZE (1..maxWLAN-Bands-r13)) OF WLAN-BandIndicator-r13 OPTIONAL +} + +CSG-ProximityIndicationParameters-r9 ::= SEQUENCE { + intraFreqProximityIndication-r9 ENUMERATED {supported} OPTIONAL, + interFreqProximityIndication-r9 ENUMERATED {supported} OPTIONAL, + utran-ProximityIndication-r9 ENUMERATED {supported} OPTIONAL +} + +NeighCellSI-AcquisitionParameters-r9 ::= SEQUENCE { + intraFreqSI-AcquisitionForHO-r9 ENUMERATED {supported} OPTIONAL, + interFreqSI-AcquisitionForHO-r9 ENUMERATED {supported} OPTIONAL, + utran-SI-AcquisitionForHO-r9 ENUMERATED {supported} OPTIONAL +} + +SON-Parameters-r9 ::= SEQUENCE { + rach-Report-r9 ENUMERATED {supported} OPTIONAL +} + +UE-BasedNetwPerfMeasParameters-r10 ::= SEQUENCE { + loggedMeasurementsIdle-r10 ENUMERATED {supported} OPTIONAL, + standaloneGNSS-Location-r10 ENUMERATED {supported} OPTIONAL +} + +UE-BasedNetwPerfMeasParameters-v1250 ::= SEQUENCE { + loggedMBSFNMeasurements-r12 ENUMERATED {supported} +} + +OTDOA-PositioningCapabilities-r10 ::= SEQUENCE { + otdoa-UE-Assisted-r10 ENUMERATED {supported}, + interFreqRSTD-Measurement-r10 ENUMERATED {supported} OPTIONAL +} + +Other-Parameters-r11 ::= SEQUENCE { + inDeviceCoexInd-r11 ENUMERATED {supported} OPTIONAL, + powerPrefInd-r11 ENUMERATED {supported} OPTIONAL, + ue-Rx-TxTimeDiffMeasurements-r11 ENUMERATED {supported} OPTIONAL +} + +Other-Parameters-v11d0 ::= SEQUENCE { + inDeviceCoexInd-UL-CA-r11 ENUMERATED {supported} OPTIONAL +} + +MBMS-Parameters-r11 ::= SEQUENCE { + mbms-SCell-r11 ENUMERATED {supported} OPTIONAL, + mbms-NonServingCell-r11 ENUMERATED {supported} OPTIONAL +} + +MBMS-Parameters-v1250 ::= SEQUENCE { + mbms-AsyncDC-r12 ENUMERATED {supported} OPTIONAL +} + +SCPTM-Parameters-r13 ::= SEQUENCE { + scptm-ParallelReception-r13 ENUMERATED {supported} OPTIONAL, + scptm-SCell-r13 ENUMERATED {supported} OPTIONAL, + scptm-NonServingCell-r13 ENUMERATED {supported} OPTIONAL, + scptm-AsyncDC-r13 ENUMERATED {supported} OPTIONAL +} + +CE-Parameters-r13 ::= SEQUENCE { + ce-ModeA-r13 ENUMERATED {supported} OPTIONAL, + ce-ModeB-r13 ENUMERATED {supported} OPTIONAL +} + +CE-Parameters-v1320 ::= SEQUENCE { + intraFreqA3-CE-ModeA-r13 ENUMERATED {supported} OPTIONAL, + intraFreqA3-CE-ModeB-r13 ENUMERATED {supported} OPTIONAL, + intraFreqHO-CE-ModeA-r13 ENUMERATED {supported} OPTIONAL, + intraFreqHO-CE-ModeB-r13 ENUMERATED {supported} OPTIONAL +} + +LAA-Parameters-r13 ::= SEQUENCE { + crossCarrierSchedulingLAA-DL-r13 ENUMERATED {supported} OPTIONAL, + csi-RS-DRS-RRM-MeasurementsLAA-r13 ENUMERATED {supported} OPTIONAL, + downlinkLAA-r13 ENUMERATED {supported} OPTIONAL, + endingDwPTS-r13 ENUMERATED {supported} OPTIONAL, + secondSlotStartingPosition-r13 ENUMERATED {supported} OPTIONAL, + tm9-LAA-r13 ENUMERATED {supported} OPTIONAL, + tm10-LAA-r13 ENUMERATED {supported} OPTIONAL +} + +LAA-Parameters-v14xy ::= SEQUENCE { + crossCarrierSchedulingLAA-UL-r14 ENUMERATED {supported} OPTIONAL, + uplinkLAA-r14 ENUMERATED {supported} OPTIONAL, + twoStepSchedulingTimingInfo-r14 ENUMERATED {nPlus1, nPlus2, nPlus3} OPTIONAL +} + +WLAN-IW-Parameters-r12 ::= SEQUENCE { + wlan-IW-RAN-Rules-r12 ENUMERATED {supported} OPTIONAL, + wlan-IW-ANDSF-Policies-r12 ENUMERATED {supported} OPTIONAL +} + +LWA-Parameters-r13 ::= SEQUENCE { + lwa-r13 ENUMERATED {supported} OPTIONAL, + lwa-SplitBearer-r13 ENUMERATED {supported} OPTIONAL, + wlan-MAC-Address-r13 OCTET STRING (SIZE (6)) OPTIONAL, + lwa-BufferSize-r13 ENUMERATED {supported} OPTIONAL +} + +WLAN-IW-Parameters-v1310 ::= SEQUENCE { + rclwi-r13 ENUMERATED {supported} OPTIONAL +} + +LWIP-Parameters-r13 ::= SEQUENCE { + lwip-r13 ENUMERATED {supported} OPTIONAL +} + +LWIP-Parameters-v14xy ::= SEQUENCE { + lwip-Aggregation-DL-r14 ENUMERATED {supported} OPTIONAL, + lwip-Aggregation-UL-r14 ENUMERATED {supported} OPTIONAL +} + +NAICS-Capability-List-r12 ::= SEQUENCE (SIZE (1..maxNAICS-Entries-r12)) OF NAICS-Capability-Entry-r12 + + +NAICS-Capability-Entry-r12 ::= SEQUENCE { + numberOfNAICS-CapableCC-r12 INTEGER(1..5), + numberOfAggregatedPRB-r12 ENUMERATED { + n50, n75, n100, n125, n150, n175, + n200, n225, n250, n275, n300, n350, + n400, n450, n500, spare}, + ... +} + +SL-Parameters-r12 ::= SEQUENCE { + commSimultaneousTx-r12 ENUMERATED {supported} OPTIONAL, + commSupportedBands-r12 FreqBandIndicatorListEUTRA-r12 OPTIONAL, + discSupportedBands-r12 SupportedBandInfoList-r12 OPTIONAL, + discScheduledResourceAlloc-r12 ENUMERATED {supported} OPTIONAL, + disc-UE-SelectedResourceAlloc-r12 ENUMERATED {supported} OPTIONAL, + disc-SLSS-r12 ENUMERATED {supported} OPTIONAL, + discSupportedProc-r12 ENUMERATED {n50, n400} OPTIONAL +} + +SL-Parameters-v1310 ::= SEQUENCE { + discSysInfoReporting-r13 ENUMERATED {supported} OPTIONAL, + commMultipleTx-r13 ENUMERATED {supported} OPTIONAL, + discInterFreqTx-r13 ENUMERATED {supported} OPTIONAL, + discPeriodicSLSS-r13 ENUMERATED {supported} OPTIONAL +} + + +SupportedBandInfoList-r12 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBandInfo-r12 + +SupportedBandInfo-r12 ::= SEQUENCE { + support-r12 ENUMERATED {supported} OPTIONAL +} + +FreqBandIndicatorListEUTRA-r12 ::= SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicator-r11 + + +UE-RadioPagingInfo-r12 ::= SEQUENCE { + ue-Category-v1250 INTEGER (0) OPTIONAL, + ..., + [[ ue-CategoryDL-v1310 ENUMERATED {m1} OPTIONAL, + ce-ModeA-r13 ENUMERATED {true} OPTIONAL, + ce-ModeB-r13 ENUMERATED {true} OPTIONAL + ]] + +} + + +UE-TimersAndConstants ::= SEQUENCE { + t300 ENUMERATED { + ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, + ms2000}, + t301 ENUMERATED { + ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, + ms2000}, + t310 ENUMERATED { + ms0, ms50, ms100, ms200, ms500, ms1000, ms2000}, + n310 ENUMERATED { + n1, n2, n3, n4, n6, n8, n10, n20}, + t311 ENUMERATED { + ms1000, ms3000, ms5000, ms10000, ms15000, + ms20000, ms30000}, + n311 ENUMERATED { + n1, n2, n3, n4, n5, n6, n8, n10}, + ..., + [[ t300-v1310 ENUMERATED { + ms2500, ms3000, ms3500, ms4000, ms5000, ms6000, ms8000, + ms10000} OPTIONAL, -- Need OR + t301-v1310 ENUMERATED { + ms2500, ms3000, ms3500, ms4000, ms5000, ms6000, ms8000, + ms10000} OPTIONAL -- Need OR + ]], + [[ t310-v1330 ENUMERATED {ms4000, ms6000} + OPTIONAL -- Need OR + ]] +} + + +VisitedCellInfoList-r12 ::= SEQUENCE (SIZE (1..maxCellHistory-r12)) OF VisitedCellInfo-r12 + +VisitedCellInfo-r12 ::= SEQUENCE { + visitedCellId-r12 CHOICE { + cellGlobalId-r12 CellGlobalIdEUTRA, + pci-arfcn-r12 SEQUENCE { + physCellId-r12 PhysCellId, + carrierFreq-r12 ARFCN-ValueEUTRA-r9 + } + } OPTIONAL, + timeSpent-r12 INTEGER (0..4095), + ... +} + + +WLAN-OffloadConfig-r12 ::= SEQUENCE { + thresholdRSRP-r12 SEQUENCE { + thresholdRSRP-Low-r12 RSRP-Range, + thresholdRSRP-High-r12 RSRP-Range + } OPTIONAL, -- Need OR + thresholdRSRQ-r12 SEQUENCE { + thresholdRSRQ-Low-r12 RSRQ-Range, + thresholdRSRQ-High-r12 RSRQ-Range + } OPTIONAL, -- Need OR + thresholdRSRQ-OnAllSymbolsWithWB-r12 SEQUENCE { + thresholdRSRQ-OnAllSymbolsWithWB-Low-r12 RSRQ-Range, + thresholdRSRQ-OnAllSymbolsWithWB-High-r12 RSRQ-Range + } OPTIONAL, -- Need OP + thresholdRSRQ-OnAllSymbols-r12 SEQUENCE { + thresholdRSRQ-OnAllSymbolsLow-r12 RSRQ-Range, + thresholdRSRQ-OnAllSymbolsHigh-r12 RSRQ-Range + } OPTIONAL, -- Need OP + thresholdRSRQ-WB-r12 SEQUENCE { + thresholdRSRQ-WB-Low-r12 RSRQ-Range, + thresholdRSRQ-WB-High-r12 RSRQ-Range + } OPTIONAL, -- Need OP + + thresholdChannelUtilization-r12 SEQUENCE { + thresholdChannelUtilizationLow-r12 INTEGER (0..255), + thresholdChannelUtilizationHigh-r12 INTEGER (0..255) + } OPTIONAL, -- Need OR + thresholdBackhaul-Bandwidth-r12 SEQUENCE { + thresholdBackhaulDL-BandwidthLow-r12 WLAN-backhaulRate-r12, + thresholdBackhaulDL-BandwidthHigh-r12 WLAN-backhaulRate-r12, + thresholdBackhaulUL-BandwidthLow-r12 WLAN-backhaulRate-r12, + thresholdBackhaulUL-BandwidthHigh-r12 WLAN-backhaulRate-r12 + } OPTIONAL, -- Need OR + thresholdWLAN-RSSI-r12 SEQUENCE { + thresholdWLAN-RSSI-Low-r12 INTEGER (0..255), + thresholdWLAN-RSSI-High-r12 INTEGER (0..255) + } OPTIONAL, -- Need OR + offloadPreferenceIndicator-r12 BIT STRING (SIZE (16)) OPTIONAL, -- Need OR + t-SteeringWLAN-r12 T-Reselection OPTIONAL, -- Need OR + ... +} + +WLAN-backhaulRate-r12 ::= ENUMERATED + {r0, r4, r8, r16, r32, r64, r128, r256, r512, + r1024, r2048, r4096, r8192, r16384, r32768, r65536, r131072, + r262144, r524288, r1048576, r2097152, r4194304, r8388608, + r16777216, r33554432, r67108864, r134217728, r268435456, + r536870912, r1073741824, r2147483648, r4294967296} + + +MBMS-NotificationConfig-r9 ::= SEQUENCE { + notificationRepetitionCoeff-r9 ENUMERATED {n2, n4}, + notificationOffset-r9 INTEGER (0..10), + notificationSF-Index-r9 INTEGER (1..6) +} + + +MBMS-ServiceList-r13 ::= SEQUENCE (SIZE (0..maxMBMS-ServiceListPerUE-r13)) OF MBMS-ServiceInfo-r13 + +MBMS-ServiceInfo-r13 ::= SEQUENCE { + tmgi-r13 TMGI-r9 +} + + +MBSFN-AreaId-r12 ::= INTEGER (0..255) + + +MBSFN-AreaInfoList-r9 ::= SEQUENCE (SIZE(1..maxMBSFN-Area)) OF MBSFN-AreaInfo-r9 + +MBSFN-AreaInfo-r9 ::= SEQUENCE { + mbsfn-AreaId-r9 MBSFN-AreaId-r12, + non-MBSFNregionLength ENUMERATED {s1, s2}, + notificationIndicator-r9 INTEGER (0..7), + mcch-Config-r9 SEQUENCE { + mcch-RepetitionPeriod-r9 ENUMERATED {rf32, rf64, rf128, rf256}, + mcch-Offset-r9 INTEGER (0..10), + mcch-ModificationPeriod-r9 ENUMERATED {rf512, rf1024}, + sf-AllocInfo-r9 BIT STRING (SIZE(6)), + signallingMCS-r9 ENUMERATED {n2, n7, n13, n19} + }, + ... +} + + +MBSFN-SubframeConfig ::= SEQUENCE { + radioframeAllocationPeriod ENUMERATED {n1, n2, n4, n8, n16, n32}, + radioframeAllocationOffset INTEGER (0..7), + subframeAllocation CHOICE { + oneFrame BIT STRING (SIZE(6)), + fourFrames BIT STRING (SIZE(24)) + } +} + +PMCH-InfoList-r9 ::= SEQUENCE (SIZE (0..maxPMCH-PerMBSFN)) OF PMCH-Info-r9 + +PMCH-InfoListExt-r12 ::= SEQUENCE (SIZE (0..maxPMCH-PerMBSFN)) OF PMCH-InfoExt-r12 + +PMCH-Info-r9 ::= SEQUENCE { + pmch-Config-r9 PMCH-Config-r9, + mbms-SessionInfoList-r9 MBMS-SessionInfoList-r9, + ... +} + +PMCH-InfoExt-r12 ::= SEQUENCE { + pmch-Config-r12 PMCH-Config-r12, + mbms-SessionInfoList-r12 MBMS-SessionInfoList-r9, + ... +} + +MBMS-SessionInfoList-r9 ::= SEQUENCE (SIZE (0..maxSessionPerPMCH)) OF MBMS-SessionInfo-r9 + +MBMS-SessionInfo-r9 ::= SEQUENCE { + tmgi-r9 TMGI-r9, + sessionId-r9 OCTET STRING (SIZE (1)) OPTIONAL, -- Need OR + logicalChannelIdentity-r9 INTEGER (0..maxSessionPerPMCH-1), + ... +} + +PMCH-Config-r9 ::= SEQUENCE { + sf-AllocEnd-r9 INTEGER (0..1535), + dataMCS-r9 INTEGER (0..28), + mch-SchedulingPeriod-r9 ENUMERATED { + rf8, rf16, rf32, rf64, rf128, rf256, rf512, rf1024}, + ... +} + +PMCH-Config-r12 ::= SEQUENCE { + sf-AllocEnd-r12 INTEGER (0..1535), + dataMCS-r12 CHOICE { + normal-r12 INTEGER (0..28), + higerOrder-r12 INTEGER (0..27) + }, + mch-SchedulingPeriod-r12 ENUMERATED { + rf4, rf8, rf16, rf32, rf64, rf128, rf256, rf512, rf1024}, + ... +} + +TMGI-r9 ::= SEQUENCE { + plmn-Id-r9 CHOICE { + plmn-Index-r9 INTEGER (1..maxPLMN-r11), + explicitValue-r9 PLMN-Identity + }, + serviceId-r9 OCTET STRING (SIZE (3)) +} + + + +SC-MTCH-InfoList-r13 ::= SEQUENCE (SIZE (0..maxSC-MTCH-r13)) OF SC-MTCH-Info-r13 + +SC-MTCH-Info-r13 ::= SEQUENCE { + mbmsSessionInfo-r13 MBMSSessionInfo-r13, + g-RNTI-r13 BIT STRING(SIZE(16)), + sc-mtch-schedulingInfo-r13 SC-MTCH-SchedulingInfo-r13 OPTIONAL, -- Need OP + sc-mtch-neighbourCell-r13 BIT STRING (SIZE(maxNeighCell-SCPTM-r13)) OPTIONAL, -- Need OP + ..., + [[ p-a-r13 ENUMERATED { + dB-6, dB-4dot77, dB-3, dB-1dot77, + dB0, dB1, dB2, dB3} OPTIONAL -- Need ON + ]] +} + +MBMSSessionInfo-r13 ::= SEQUENCE { + tmgi-r13 TMGI-r9, + sessionId-r13 OCTET STRING (SIZE (1)) OPTIONAL -- Need OR +} + +SC-MTCH-SchedulingInfo-r13::= SEQUENCE { + onDurationTimerSCPTM-r13 ENUMERATED { + psf1, psf2, psf3, psf4, psf5, psf6, + psf8, psf10, psf20, psf30, psf40, + psf50, psf60, psf80, psf100, + psf200}, + drx-InactivityTimerSCPTM-r13 ENUMERATED { + psf0, psf1, psf2, psf4, psf8, + psf10, psf20, psf40, + psf80, psf160, ps320, + psf640, psf960, + psf1280, psf1920, psf2560}, + schedulingPeriodStartOffsetSCPTM-r13 CHOICE { + sf10 INTEGER(0..9), + sf20 INTEGER(0..19), + sf32 INTEGER(0..31), + sf40 INTEGER(0..39), + sf64 INTEGER(0..63), + sf80 INTEGER(0..79), + sf128 INTEGER(0..127), + sf160 INTEGER(0..159), + sf256 INTEGER(0..255), + sf320 INTEGER(0..319), + sf512 INTEGER(0..511), + sf640 INTEGER(0..639), + sf1024 INTEGER(0..1023), + sf2048 INTEGER(0..2048), + sf4096 INTEGER(0..4096), + sf8192 INTEGER(0..8192) + }, + ... +} + + +SCPTM-NeighbourCellList-r13 ::= SEQUENCE (SIZE (1..maxNeighCell-SCPTM-r13)) OF PCI-ARFCN-r13 + +PCI-ARFCN-r13 ::= SEQUENCE { + physCellId-r13 PhysCellId, + carrierFreq-r13 ARFCN-ValueEUTRA-r9 OPTIONAL +} + + +SL-CommConfig-r12 ::= SEQUENCE { + commTxResources-r12 CHOICE { + release NULL, + setup CHOICE { + scheduled-r12 SEQUENCE { + sl-RNTI-r12 C-RNTI, + mac-MainConfig-r12 MAC-MainConfigSL-r12, + sc-CommTxConfig-r12 SL-CommResourcePool-r12, + mcs-r12 INTEGER (0..28) OPTIONAL -- Need OP + }, + ue-Selected-r12 SEQUENCE { + -- Pool for normal usage + commTxPoolNormalDedicated-r12 SEQUENCE { + poolToReleaseList-r12 SL-TxPoolToReleaseList-r12 OPTIONAL, -- Need ON + poolToAddModList-r12 SL-CommTxPoolToAddModList-r12 OPTIONAL -- Need ON + } + } + } + } OPTIONAL, -- Need ON + ..., + [[ commTxResources-v1310 CHOICE { + release NULL, + setup CHOICE { + scheduled-v1310 SEQUENCE { + logicalChGroupInfoList-r13 LogicalChGroupInfoList-r13, + multipleTx-r13 BOOLEAN + }, + ue-Selected-v1310 SEQUENCE { + commTxPoolNormalDedicatedExt-r13 SEQUENCE { + poolToReleaseListExt-r13 SL-TxPoolToReleaseListExt-r13 OPTIONAL, -- Need ON + poolToAddModListExt-r13 SL-CommTxPoolToAddModListExt-r13 OPTIONAL -- Need ON + } + } + } + } OPTIONAL, -- Need ON + commTxAllowRelayDedicated-r13 BOOLEAN OPTIONAL -- Need ON + ]] +} + +LogicalChGroupInfoList-r13 ::= SEQUENCE (SIZE (1..maxLCG-r13)) OF SL-PriorityList-r13 + +SL-CommTxPoolToAddModList-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF SL-CommTxPoolToAddMod-r12 + +SL-CommTxPoolToAddModListExt-r13 ::= SEQUENCE (SIZE (1..maxSL-TxPool-v1310)) OF SL-CommTxPoolToAddModExt-r13 + +SL-CommTxPoolToAddMod-r12 ::= SEQUENCE { + poolIdentity-r12 SL-TxPoolIdentity-r12, + pool-r12 SL-CommResourcePool-r12 +} + +SL-CommTxPoolToAddModExt-r13 ::= SEQUENCE { + poolIdentity-v1310 SL-TxPoolIdentity-v1310, + pool-r13 SL-CommResourcePool-r12 +} + +MAC-MainConfigSL-r12 ::= SEQUENCE { + periodic-BSR-TimerSL PeriodicBSR-Timer-r12 OPTIONAL, -- Need ON + retx-BSR-TimerSL RetxBSR-Timer-r12 +} + + +SL-CommTxPoolList-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF SL-CommResourcePool-r12 + +SL-CommTxPoolListExt-r13 ::= SEQUENCE (SIZE (1..maxSL-TxPool-v1310)) OF SL-CommResourcePool-r12 + +SL-CommTxPoolListV2X-r14 ::= SEQUENCE (SIZE (1..maxSL-V2X-TxPool-r14)) OF SL-CommResourcePoolV2X-r14 + +SL-CommRxPoolList-r12 ::= SEQUENCE (SIZE (1..maxSL-RxPool-r12)) OF SL-CommResourcePool-r12 + +SL-CommRxPoolListV2X-r14 ::= SEQUENCE (SIZE (1..maxSL-V2X-RxPool-r14)) OF SL-CommResourcePoolV2X-r14 + +SL-CommResourcePool-r12 ::= SEQUENCE { + sc-CP-Len-r12 SL-CP-Len-r12, + sc-Period-r12 SL-PeriodComm-r12, + sc-TF-ResourceConfig-r12 SL-TF-ResourceConfig-r12, + data-CP-Len-r12 SL-CP-Len-r12, + dataHoppingConfig-r12 SL-HoppingConfigComm-r12, + ue-SelectedResourceConfig-r12 SEQUENCE { + data-TF-ResourceConfig-r12 SL-TF-ResourceConfig-r12, + trpt-Subset-r12 SL-TRPT-Subset-r12 OPTIONAL -- Need OP + } OPTIONAL, -- Need OR + rxParametersNCell-r12 SEQUENCE { + tdd-Config-r12 TDD-Config OPTIONAL, -- Need OP + syncConfigIndex-r12 INTEGER (0..15) + } OPTIONAL, -- Need OR + txParameters-r12 SEQUENCE { + sc-TxParameters-r12 SL-TxParameters-r12, + dataTxParameters-r12 SL-TxParameters-r12 + } OPTIONAL, -- Cond Tx + ..., + [[ priorityList-r13 SL-PriorityList-r13 OPTIONAL -- Cond Tx + ]] + +} + +SL-CommResourcePoolV2X-r14 ::= SEQUENCE { + sl-OffsetIndicator-r14 SL-OffsetIndicator-r12 OPTIONAL, -- Need OR + sl-Subframe-r14 SubframeBitmapSL-r14, + adjacencyPSCCH-PSSCH-r14 BOOLEAN, + sizeSubchannel-r14 ENUMERATED { + n4, n5, n6, n8, n9, n10, n12, n15, n16, n18, n20, n25, n30, + n48, n50, n72, n75, n96, n100, spare13, spare12, spare11, + spare10, spare9, spare8, spare7, spare6, spare5, spare4, + spare3, spare2, spare1}, + numSubchannel-r14 ENUMERATED {n1, n3, n5, n10, n15, n20, spare2, spare1}, + startRB-Subchannel-r14 INTEGER (0..99), + startRB-PSCCH-Pool-r14 INTEGER (0..99) OPTIONAL, -- Need OR + rxParametersNCell-r14 SEQUENCE { + tdd-Config-r14 TDD-Config OPTIONAL, -- Need OP + syncConfigIndex-r14 INTEGER (0..15) + } OPTIONAL, -- Need OR + dataTxParameters-r14 SL-TxParameters-r12 OPTIONAL, -- Cond Tx + zoneID-r14 INTEGER (0..7) OPTIONAL, -- Need OR, + ... +} + +SL-TRPT-Subset-r12 ::= BIT STRING (SIZE (3..5)) + + +SL-CP-Len-r12 ::= ENUMERATED {normal, extended} + + +SL-DiscConfig-r12 ::= SEQUENCE { + discTxResources-r12 CHOICE { + release NULL, + setup CHOICE { + scheduled-r12 SEQUENCE { + discTxConfig-r12 SL-DiscResourcePool-r12 OPTIONAL, -- Need ON + discTF-IndexList-r12 SL-TF-IndexPairList-r12 OPTIONAL, -- Need ON + discHoppingConfig-r12 SL-HoppingConfigDisc-r12 + OPTIONAL -- Need ON + }, + ue-Selected-r12 SEQUENCE { + discTxPoolDedicated-r12 SEQUENCE { + poolToReleaseList-r12 SL-TxPoolToReleaseList-r12 OPTIONAL, -- Need ON + poolToAddModList-r12 SL-DiscTxPoolToAddModList-r12 OPTIONAL -- Need ON + } OPTIONAL -- Need ON + } + } + } OPTIONAL, -- Need ON + ..., + [[ discTF-IndexList-v1260 CHOICE { + release NULL, + setup SEQUENCE { + discTF-IndexList-r12b SL-TF-IndexPairList-r12b + } + } OPTIONAL -- Need ON + ]], + [[ discTxResourcesPS-r13 CHOICE { + release NULL, + setup CHOICE { + scheduled-r13 SL-DiscTxConfigScheduled-r13, + ue-Selected-r13 SEQUENCE { + discTxPoolPS-Dedicated-r13 SL-DiscTxPoolDedicated-r13 + } + } + } OPTIONAL, -- Need ON + discTxInterFreqInfo-r13 CHOICE { + release NULL, + setup SEQUENCE { + discTxCarrierFreq-r13 ARFCN-ValueEUTRA-r9 OPTIONAL, -- Need OR + discTxRefCarrierDedicated-r13 SL-DiscTxRefCarrierDedicated-r13 OPTIONAL, -- Need OR + discTxInfoInterFreqListAdd-r13 SL-DiscTxInfoInterFreqListAdd-r13 OPTIONAL -- Need ON + } + } OPTIONAL, -- Need ON + gapRequestsAllowedDedicated-r13 BOOLEAN OPTIONAL, -- Need ON + discRxGapConfig-r13 CHOICE { + release NULL, + setup SL-GapConfig-r13 + } OPTIONAL, -- Need ON + discTxGapConfig-r13 CHOICE { + release NULL, + setup SL-GapConfig-r13 + } OPTIONAL, -- Need ON + discSysInfoToReportConfig-r13 CHOICE { + release NULL, + setup SL-DiscSysInfoToReportFreqList-r13 + } OPTIONAL -- Need ON + ]] +} + +SL-DiscSysInfoToReportFreqList-r13 ::= SEQUENCE (SIZE (1..maxFreq)) OF ARFCN-ValueEUTRA-r9 + +SL-DiscTxInfoInterFreqListAdd-r13 ::= SEQUENCE { + discTxFreqToAddModList-r13 SEQUENCE (SIZE (1..maxFreq)) OF SL-DiscTxResourceInfoPerFreq-r13 OPTIONAL, -- Need ON + discTxFreqToReleaseList-r13 SEQUENCE (SIZE (1..maxFreq)) OF ARFCN-ValueEUTRA-r9 OPTIONAL, -- Need ON + ... +} + +SL-DiscTxResourceInfoPerFreq-r13 ::= SEQUENCE { + discTxCarrierFreq-r13 ARFCN-ValueEUTRA-r9, + discTxResources-r13 SL-DiscTxResource-r13 OPTIONAL, -- Need OR + discTxResourcesPS-r13 SL-DiscTxResource-r13 OPTIONAL, -- Need OR + discTxRefCarrierDedicated-r13 SL-DiscTxRefCarrierDedicated-r13 OPTIONAL, -- Need OR + discCellSelectionInfo-r13 CellSelectionInfoNFreq-r13 OPTIONAL, -- Need OR + ... +} + +SL-DiscTxResource-r13 ::= CHOICE { + release NULL, + setup CHOICE { + scheduled-r13 SL-DiscTxConfigScheduled-r13, + ue-Selected-r13 SL-DiscTxPoolDedicated-r13 + } +} + +SL-DiscTxPoolToAddModList-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF SL-DiscTxPoolToAddMod-r12 + +SL-DiscTxPoolToAddMod-r12 ::= SEQUENCE { + poolIdentity-r12 SL-TxPoolIdentity-r12, + pool-r12 SL-DiscResourcePool-r12 +} + +SL-DiscTxConfigScheduled-r13 ::= SEQUENCE { + discTxConfig-r13 SL-DiscResourcePool-r12 OPTIONAL, -- Need ON + discTF-IndexList-r13 SL-TF-IndexPairList-r12b OPTIONAL, -- Need ON + discHoppingConfig-r13 SL-HoppingConfigDisc-r12 OPTIONAL,-- Need ON + ... +} + +SL-DiscTxPoolDedicated-r13 ::= SEQUENCE { + poolToReleaseList-r13 SL-TxPoolToReleaseList-r12 OPTIONAL, -- Need ON + poolToAddModList-r13 SL-DiscTxPoolToAddModList-r12 OPTIONAL -- Need ON +} + +SL-TF-IndexPairList-r12 ::= SEQUENCE (SIZE (1..maxSL-TF-IndexPair-r12)) OF SL-TF-IndexPair-r12 + +SL-TF-IndexPair-r12 ::= SEQUENCE { + discSF-Index-r12 INTEGER (1.. 200) OPTIONAL, -- Need ON + discPRB-Index-r12 INTEGER (1.. 50) OPTIONAL -- Need ON +} + +SL-TF-IndexPairList-r12b ::= SEQUENCE (SIZE (1..maxSL-TF-IndexPair-r12)) OF SL-TF-IndexPair-r12b + +SL-TF-IndexPair-r12b ::= SEQUENCE { + discSF-Index-r12b INTEGER (0..209) OPTIONAL, -- Need ON + discPRB-Index-r12b INTEGER (0..49) OPTIONAL -- Need ON +} + +SL-DiscTxRefCarrierDedicated-r13 ::= CHOICE { + pCell NULL, + sCell SCellIndex-r10 +} + + +SL-DiscTxPoolList-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF SL-DiscResourcePool-r12 + +SL-DiscRxPoolList-r12 ::= SEQUENCE (SIZE (1..maxSL-RxPool-r12)) OF SL-DiscResourcePool-r12 + +SL-DiscResourcePool-r12 ::= SEQUENCE { + cp-Len-r12 SL-CP-Len-r12, + discPeriod-r12 ENUMERATED {rf32, rf64, rf128, + rf256, rf512, rf1024, rf16-v1310, spare}, + numRetx-r12 INTEGER (0..3), + numRepetition-r12 INTEGER (1..50), + tf-ResourceConfig-r12 SL-TF-ResourceConfig-r12, + txParameters-r12 SEQUENCE { + txParametersGeneral-r12 SL-TxParameters-r12, + ue-SelectedResourceConfig-r12 SEQUENCE { + poolSelection-r12 CHOICE { + rsrpBased-r12 SL-PoolSelectionConfig-r12, + random-r12 NULL + }, + txProbability-r12 ENUMERATED {p25, p50, p75, p100} + } OPTIONAL -- Need OR + } OPTIONAL, -- Cond Tx + rxParameters-r12 SEQUENCE { + tdd-Config-r12 TDD-Config OPTIONAL, -- Need OR + syncConfigIndex-r12 INTEGER (0..15) + } OPTIONAL, -- Need OR + ..., + [[ discPeriod-v1310 CHOICE { + release NULL, + setup ENUMERATED {rf4, rf6, rf7, rf8, + rf12, rf14, rf24, rf28} + } OPTIONAL, -- Need ON + rxParamsAddNeighFreq-r13 CHOICE { + release NULL, + setup SEQUENCE { + physCellId-r13 PhysCellIdList-r13 + } + } OPTIONAL, -- Need ON + txParamsAddNeighFreq-r13 CHOICE { + release NULL, + setup SEQUENCE { + physCellId-r13 PhysCellIdList-r13, + p-Max P-Max OPTIONAL, -- Need OP + tdd-Config-r13 TDD-Config OPTIONAL, -- Cond TDD-OR + tdd-Config-v1130 TDD-Config-v1130 OPTIONAL, -- Cond TDD-OR + freqInfo SEQUENCE { + ul-CarrierFreq ARFCN-ValueEUTRA OPTIONAL, -- Need OP + ul-Bandwidth ENUMERATED {n6, n15, n25, n50, n75, n100} + OPTIONAL, -- Need OP + additionalSpectrumEmission AdditionalSpectrumEmission + }, + referenceSignalPower INTEGER (-60..50), + syncConfigIndex-r13 INTEGER (0..15) OPTIONAL -- Need OR + } + } OPTIONAL -- Need ON + ]] +} + +PhysCellIdList-r13 ::= SEQUENCE (SIZE (1.. maxSL-DiscCells-r13)) OF PhysCellId + +SL-PoolSelectionConfig-r12 ::= SEQUENCE { + threshLow-r12 RSRP-RangeSL2-r12, + threshHigh-r12 RSRP-RangeSL2-r12 +} + + +SL-DiscTxPowerInfoList-r12 ::= SEQUENCE (SIZE (maxSL-DiscPowerClass-r12)) OF SL-DiscTxPowerInfo-r12 + +SL-DiscTxPowerInfo-r12 ::= SEQUENCE { + discMaxTxPower-r12 P-Max, + ... +} + + +SL-GapConfig-r13 ::= SEQUENCE { + gapPatternList-r13 SL-GapPatternList-r13 +} + +SL-GapPatternList-r13 ::= SEQUENCE (SIZE (1..maxSL-GP-r13)) OF SL-GapPattern-r13 + +SL-GapPattern-r13 ::= SEQUENCE { + gapPeriod-r13 ENUMERATED {sf40, sf60, sf70, sf80, sf120, sf140, sf160, + sf240, sf280, sf320, sf640, sf1280, sf2560, sf5120, + sf10240}, + gapOffset-r12 SL-OffsetIndicator-r12, + gapSubframeBitmap-r13 BIT STRING (SIZE (1..10240)), + ... +} + + +SL-GapRequest-r13 ::= SEQUENCE (SIZE (1..maxFreq)) OF SL-GapFreqInfo-r13 + +SL-GapFreqInfo-r13 ::= SEQUENCE { + carrierFreq-r13 ARFCN-ValueEUTRA-r9 OPTIONAL, + gapPatternList-r13 SL-GapPatternList-r13 +} + + +SL-HoppingConfigComm-r12 ::= SEQUENCE { + hoppingParameter-r12 INTEGER (0..504), + numSubbands-r12 ENUMERATED {ns1, ns2, ns4}, + rb-Offset-r12 INTEGER (0..110) +} + +SL-HoppingConfigDisc-r12 ::= SEQUENCE { + a-r12 INTEGER (1..200), + b-r12 INTEGER (1..10), + c-r12 ENUMERATED {n1, n5} +} + + +SL-InterFreqInfoListV2X-r14 ::= SEQUENCE (SIZE (1..maxFreq)) OF SL-InterFreqInfoV2X-r14 + +SL-InterFreqInfoV2X-r14::= SEQUENCE { + v2x-CommCarrierFreq-r14 ARFCN-ValueEUTRA-r9, + typeTxSync-r14 ENUMERATED {gnss, enb} OPTIONAL, -- Need OR + v2x-SchedulingPool-r14 SL-CommResourcePoolV2X-r14 OPTIONAL, -- Need OR + ... +} + + +SL-OffsetIndicator-r12 ::= CHOICE { + small-r12 INTEGER (0..319), + large-r12 INTEGER (0..10239) +} + +SL-OffsetIndicatorSync-r12 ::= INTEGER (0..39) + +SL-OffsetIndicatorSync-v14xy ::= INTEGER (40..159) + + +SL-PeriodComm-r12 ::= ENUMERATED {sf40, sf60, sf70, sf80, sf120, sf140, + sf160, sf240, sf280, sf320, spare6, spare5, + spare4, spare3, spare2, spare} + + +SL-PriorityList-r13 ::= SEQUENCE (SIZE (1..maxSL-Prio-r13)) OF SL-Priority-r13 + +SL-Priority-r13 ::= INTEGER (1..8) + + +SL-PSSCH-TxConfigList-r14 ::= SEQUENCE (SIZE (1..maxPSSCH-TxConfig-r14)) OF SL-PSSCH-TxConfig-r14 + +SL-PSSCH-TxConfig-r14 ::= SEQUENCE { + typeTxSync-r14 ENUMERATED {gnss, enb, ue, spare1} OPTIONAL, -- Need OR + thresUE-Speed-r14 ENUMERATED {kmph60, kmph80, kmph100, kmph120, + kmph140, kmph160, kmph180, kmph200}, + parametersAboveThres-r14 SL-PSSCH-TxParameters-r14, + parametersBelowThres-r14 SL-PSSCH-TxParameters-r14, + ... +} + +SL-PSSCH-TxParameters-r14 ::= SEQUENCE { + minMCS-PSSCH-r14 INTEGER (0..31), + maxMCS-PSSCH-r14 INTEGER (0..31), + minRB-NumberPSSCH-r14 INTEGER (1..100), + maxRB-NumberPSSCH-r14 INTEGER (1..100), + allowedRetxNumberPSSCH-r14 ENUMERATED {n0, n1, both, spare1} +} + + +SL-RestrictResourceReservationPeriodList-r14 ::= SEQUENCE (SIZE (1..maxReservationPeriod-r14)) OF SL-RestrictResourceReservationPeriod-r14 + +SL-RestrictResourceReservationPeriod-r14 ::= ENUMERATED {v0dot2, v0dot5, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, spare4,spare3, spare2, spare1} + + +SLSSID-r12 ::= INTEGER (0..167) + + +SL-SyncConfigList-r12 ::= SEQUENCE (SIZE (1..maxSL-SyncConfig-r12)) OF SL-SyncConfig-r12 + +SL-SyncConfigListV2X-r14 ::= SEQUENCE (SIZE (1.. maxSL-V2X-SyncConfig-r14)) OF SL-SyncConfig-r12 + +SL-SyncConfig-r12 ::= SEQUENCE { + syncCP-Len-r12 SL-CP-Len-r12, + syncOffsetIndicator-r12 SL-OffsetIndicatorSync-r12, + slssid-r12 SLSSID-r12, + txParameters-r12 SEQUENCE { + syncTxParameters-r12 SL-TxParameters-r12, + syncTxThreshIC-r12 RSRP-RangeSL-r12, + syncInfoReserved-r12 BIT STRING (SIZE (19)) OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + rxParamsNCell-r12 SEQUENCE { + physCellId-r12 PhysCellId, + discSyncWindow-r12 ENUMERATED {w1, w2} + } OPTIONAL, -- Need OR + ..., + [[ syncTxPeriodic-r13 ENUMERATED {true} OPTIONAL -- Need OR + ]], + [[ syncOffsetIndicator-v14xy SL-OffsetIndicatorSync-v14xy OPTIONAL -- Need OR + ]] +} + +SL-SyncConfigListNFreq-r13 ::= SEQUENCE (SIZE (1..maxSL-SyncConfig-r12)) OF SL-SyncConfigNFreq-r13 + +SL-SyncConfigNFreq-r13 ::= SEQUENCE { + asyncParameters-r13 SEQUENCE { + syncCP-Len-r13 SL-CP-Len-r12, + syncOffsetIndicator-r13 SL-OffsetIndicatorSync-r12, + slssid-r13 SLSSID-r12 + } OPTIONAL, -- Need OR + txParameters-r13 SEQUENCE { + syncTxParameters-r13 SL-TxParameters-r12, + syncTxThreshIC-r13 RSRP-RangeSL-r12, + syncInfoReserved-r13 BIT STRING (SIZE (19)) OPTIONAL, -- Need OR + syncTxPeriodic-r13 ENUMERATED {true} OPTIONAL -- Need OR + } OPTIONAL, -- Need OR + rxParameters-r13 SEQUENCE { + discSyncWindow-r13 ENUMERATED {w1, w2} + } OPTIONAL, -- Need OR + ... +} + + +SL-DiscSysInfoReport-r13 ::= SEQUENCE { + plmn-IdentityList-r13 PLMN-IdentityList OPTIONAL, + cellIdentity-13 CellIdentity OPTIONAL, + carrierFreqInfo-13 ARFCN-ValueEUTRA-r9 OPTIONAL, + discRxResources-r13 SL-DiscRxPoolList-r12 OPTIONAL, + discTxPoolCommon-r13 SL-DiscTxPoolList-r12 OPTIONAL, + discTxPowerInfo-r13 SL-DiscTxPowerInfoList-r12 OPTIONAL, + discSyncConfig-r13 SL-SyncConfigNFreq-r13 OPTIONAL, + discCellSelectionInfo-r13 SEQUENCE { + q-RxLevMin-r13 Q-RxLevMin, + q-RxLevMinOffset-r13 INTEGER (1..8) OPTIONAL + } OPTIONAL, + cellReselectionInfo-r13 SEQUENCE { + q-Hyst-r13 ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24}, + q-RxLevMin-r13 Q-RxLevMin, + t-ReselectionEUTRA-r13 T-Reselection + } OPTIONAL, + tdd-Config-r13 TDD-Config OPTIONAL, + freqInfo-r13 SEQUENCE { + ul-CarrierFreq-r13 ARFCN-ValueEUTRA OPTIONAL, + ul-Bandwidth-r13 ENUMERATED {n6, n15, n25, n50, n75, n100} + OPTIONAL, + additionalSpectrumEmission-r13 AdditionalSpectrumEmission OPTIONAL + } OPTIONAL, + p-Max-r13 P-Max OPTIONAL, + referenceSignalPower-r13 INTEGER (-60..50) OPTIONAL, + ... +} + + +SL-TF-ResourceConfig-r12 ::= SEQUENCE { + prb-Num-r12 INTEGER (1..100), + prb-Start-r12 INTEGER (0..99), + prb-End-r12 INTEGER (0..99), + offsetIndicator-r12 SL-OffsetIndicator-r12, + subframeBitmap-r12 SubframeBitmapSL-r12 +} + +SubframeBitmapSL-r12 ::= CHOICE { + bs4-r12 BIT STRING (SIZE (4)), + bs8-r12 BIT STRING (SIZE (8)), + bs12-r12 BIT STRING (SIZE (12)), + bs16-r12 BIT STRING (SIZE (16)), + bs30-r12 BIT STRING (SIZE (30)), + bs40-r12 BIT STRING (SIZE (40)), + bs42-r12 BIT STRING (SIZE (42)) +} + +SubframeBitmapSL-r14 ::= CHOICE { + bs16-r14 BIT STRING (SIZE (16)), + bs20-r14 BIT STRING (SIZE (20)), + bs100-r14 BIT STRING (SIZE (100)) +} + + +SL-ThresPSSCH-RSRP-List-r14 ::= SEQUENCE (SIZE (1..64)) OF SL-ThresPSSCH-RSRP-r14 + +SL-ThresPSSCH-RSRP-r14 ::= INTEGER (0..66) + + +SL-TxParameters-r12 ::= SEQUENCE { + alpha-r12 Alpha-r12, + p0-r12 P0-SL-r12 +} + +P0-SL-r12 ::= INTEGER (-126..31) + + +SL-TxPoolIdentity-r12 ::= INTEGER (1.. maxSL-TxPool-r12) + +SL-TxPoolIdentity-v1310 ::= INTEGER (maxSL-TxPool-r12Plus1-r13.. maxSL-TxPool-r13) + +SL-V2X-TxPoolIdentity-r14 ::= INTEGER (1.. maxSL-V2X-TxPool-r14) + + +SL-TxPoolToReleaseList-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF SL-TxPoolIdentity-r12 + +SL-TxPoolToReleaseListExt-r13 ::= SEQUENCE (SIZE (1..maxSL-TxPool-v1310)) OF SL-TxPoolIdentity-v1310 + + +SL-V2X-ConfigDedicated-r14 ::= SEQUENCE { + commTxResources-r14 CHOICE { + release NULL, + setup CHOICE { + scheduled-r14 SEQUENCE { + sl-D-RNTI-r14 C-RNTI, + mac-MainConfig-r14 MAC-MainConfigSL-r12 OPTIONAL, -- Need OP + v2x-SchedulingPool-r14 SL-CommResourcePoolV2X-r14 OPTIONAL, -- Need OP + mcs-r14 INTEGER (0..31) OPTIONAL, -- Need OP + logicalChGroupInfoList-r14 LogicalChGroupInfoList-r13 + }, + ue-Selected-r14 SEQUENCE { + -- Pool for normal usage + v2x-CommTxPoolNormalDedicated-r14 SEQUENCE { + poolToReleaseList-r14 SL-TxPoolToReleaseListV2X-r14 OPTIONAL, -- Need ON + poolToAddModList-r14 SL-TxPoolToAddModListV2X-r14 OPTIONAL, -- Need ON + v2x-CommTxPoolSensingConfig-r14 SL-CommTxPoolSensingConfig-r14 + OPTIONAL -- Need ON + } + } + } + } OPTIONAL, -- Need ON + v2x-InterFreqInfoList-r14 SL-InterFreqInfoListV2X-r14 OPTIONAL, -- Need ON + ... +} + +SL-TxPoolToAddModListV2X-r14 ::= SEQUENCE { + poolIdentity-r14 SL-V2X-TxPoolIdentity-r14, + pool-r14 SL-CommResourcePoolV2X-r14 +} + +SL-TxPoolToReleaseListV2X-r14 ::= SEQUENCE (SIZE (1.. maxSL-V2X-TxPool-r14)) OF SL-V2X-TxPoolIdentity-r14 + + +SL-ZoneConfig-r14 ::= SEQUENCE { + zoneLength-r14 ENUMERATED { m5, m10, m20, m50, m100, m200, m500, spare1} OPTIONAL, -- Need OR + zoneWidth-r14 ENUMERATED { m5, m10, m20, m50, m100, m200, m500, spare1} OPTIONAL, -- Need OR + zoneIdLongiMod-r14 INTEGER (1..4) OPTIONAL, -- Need OR + zoneIdLatiMod-r14 INTEGER (1..4) OPTIONAL -- Need OR +} + + +maxACDC-Cat-r13 INTEGER ::= 16 -- Maximum number of ACDC categories (per PLMN) +maxAvailNarrowBands-r13 INTEGER ::= 16 -- Maximum number of narrowbands +maxBandComb-r10 INTEGER ::= 128 -- Maximum number of band combinations. +maxBandComb-r11 INTEGER ::= 256 -- Maximum number of additional band combinations. +maxBandComb-r13 INTEGER ::= 384 -- Maximum number of band combinations in Rel-13 +maxBands INTEGER ::= 64 -- Maximum number of bands listed in EUTRA UE caps +maxBandwidthClass-r10 INTEGER ::= 16 -- Maximum number of supported CA BW classes per band +maxBandwidthCombSet-r10 INTEGER ::= 32 -- Maximum number of bandwidth combination sets per + -- supported band combination +maxCDMA-BandClass INTEGER ::= 32 -- Maximum value of the CDMA band classes +maxCE-Level-r13 INTEGER ::= 4 -- Maximum number of CE levels +maxCellBlack INTEGER ::= 16 -- Maximum number of blacklisted physical cell identity + -- ranges listed in SIB type 4 and 5 +maxCellHistory-r12 INTEGER ::= 16 -- Maximum number of visited EUTRA cells reported +maxCellInfoGERAN-r9 INTEGER ::= 32 -- Maximum number of GERAN cells for which system in- + -- formation can be provided as redirection assistance +maxCellInfoUTRA-r9 INTEGER ::= 16 -- Maximum number of UTRA cells for which system + -- information can be provided as redirection + -- assistance +maxCombIDC-r11 INTEGER ::= 128 -- Maximum number of reported UL CA combinations +maxCSI-IM-r11 INTEGER ::= 3 -- Maximum number of CSI-IM configurations + -- (per carrier frequency) +maxCSI-IM-r12 INTEGER ::= 4 -- Maximum number of CSI-IM configurations + -- (per carrier frequency) +minCSI-IM-r13 INTEGER ::= 5 -- Minimum number of CSI IM configurations from which + -- REL-13 extension is used +maxCSI-IM-r13 INTEGER ::= 24 -- Maximum number of CSI-IM configurations + -- (per carrier frequency) +maxCSI-IM-v1310 INTEGER ::= 20 -- Maximum number of additional CSI-IM configurations + -- (per carrier frequency) +maxCSI-Proc-r11 INTEGER ::= 4 -- Maximum number of CSI processes (per carrier + -- frequency) +maxCSI-RS-NZP-r11 INTEGER ::= 3 -- Maximum number of CSI RS resource + -- configurations using non-zero Tx power + -- (per carrier frequency) +minCSI-RS-NZP-r13 INTEGER ::= 4 -- Minimum number of CSI RS resource from which + -- REL-13 extension is used +maxCSI-RS-NZP-r13 INTEGER ::= 24 -- Maximum number of CSI RS resource + -- configurations using non-zero Tx power + -- (per carrier frequency) +maxCSI-RS-NZP-v1310 INTEGER ::= 21 -- Maximum number of additional CSI RS resource + -- configurations using non-zero Tx power + -- (per carrier frequency) +maxCSI-RS-ZP-r11 INTEGER ::= 4 -- Maximum number of CSI RS resource + -- configurations using zero Tx power(per carrier + -- frequency) +maxCQI-ProcExt-r11 INTEGER ::= 3 -- Maximum number of additional periodic CQI + -- configurations (per carrier frequency) +maxFreqUTRA-TDD-r10 INTEGER ::= 6 -- Maximum number of UTRA TDD carrier frequencies for + -- which system information can be provided as + -- redirection assistance +maxCellInter INTEGER ::= 16 -- Maximum number of neighbouring inter-frequency + -- cells listed in SIB type 5 +maxCellIntra INTEGER ::= 16 -- Maximum number of neighbouring intra-frequency + -- cells listed in SIB type 4 +maxCellListGERAN INTEGER ::= 3 -- Maximum number of lists of GERAN cells +maxCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the + -- cell lists in a measurement object +maxCellReport INTEGER ::= 8 -- Maximum number of reported cells/CSI-RS resources +maxCSI-RS-Meas-r12 INTEGER ::= 96 -- Maximum number of entries in the CSI-RS list + -- in a measurement object +maxDRB INTEGER ::= 11 -- Maximum number of Data Radio Bearers +maxDS-Duration-r12 INTEGER ::= 5 -- Maximum number of subframes in a discovery signals + -- occasion +maxDS-ZTP-CSI-RS-r12 INTEGER ::= 5 -- Maximum number of zero transmission power CSI-RS for + -- a serving cell concerning discovery signals +maxEARFCN INTEGER ::= 65535 -- Maximum value of EUTRA carrier frequency +maxEARFCN-Plus1 INTEGER ::= 65536 -- Lowest value extended EARFCN range +maxEARFCN2 INTEGER ::= 262143 -- Highest value extended EARFCN range +maxEPDCCH-Set-r11 INTEGER ::= 2 -- Maximum number of EPDCCH sets +maxFBI INTEGER ::= 64 -- Maximum value of fequency band indicator +maxFBI-Plus1 INTEGER ::= 65 -- Lowest value extended FBI range +maxFBI2 INTEGER ::= 256 -- Highest value extended FBI range +maxFreq INTEGER ::= 8 -- Maximum number of carrier frequencies +maxFreqIDC-r11 INTEGER ::= 32 -- Maximum number of carrier frequencies that are + -- affected by the IDC problems +maxFreqMBMS-r11 INTEGER ::= 5 -- Maximum number of carrier frequencies for which an + -- MBMS capable UE may indicate an interest +maxGERAN-SI INTEGER ::= 10 -- Maximum number of GERAN SI blocks that can be + -- provided as part of NACC information +maxGNFG INTEGER ::= 16 -- Maximum number of GERAN neighbour freq groups +maxLCG-r13 INTEGER ::= 4 -- Maximum number of logical channel groups +maxLogMeasReport-r10 INTEGER ::= 520 -- Maximum number of logged measurement entries + -- that can be reported by the UE in one message +maxMBSFN-Allocations INTEGER ::= 8 -- Maximum number of MBSFN frame allocations with + -- different offset +maxMBSFN-Area INTEGER ::= 8 +maxMBSFN-Area-1 INTEGER ::= 7 +maxMBMS-ServiceListPerUE-r13 INTEGER ::= 15 -- Maximum number of services which the UE can + -- include in the MBMS interest indication +maxMeasId INTEGER ::= 32 +maxMeasId-Plus1 INTEGER ::= 33 +maxMeasId-r12 INTEGER ::= 64 +maxMultiBands INTEGER ::= 8 -- Maximum number of additional frequency bands + -- that a cell belongs to +maxNS-Pmax-r10 INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxNAICS-Entries-r12 INTEGER ::= 8 -- Maximum number of supported NAICS combination(s) +maxNeighCell-r12 INTEGER ::= 8 -- Maximum number of neighbouring cells in NAICS + -- configuration (per carrier frequency) +maxNeighCell-SCPTM-r13 INTEGER ::= 8 -- Maximum number of SCPTM neighbour cells +maxObjectId INTEGER ::= 32 +maxObjectId-Plus1-r13 INTEGER ::= 33 +maxObjectId-r13 INTEGER ::= 64 +maxP-a-PerNeighCell-r12 INTEGER ::= 3 -- Maximum number of power offsets for a neighbour cell + -- in NAICS configuration +maxPageRec INTEGER ::= 16 -- +maxPhysCellIdRange-r9 INTEGER ::= 4 -- Maximum number of physical cell identity ranges +maxPLMN-r11 INTEGER ::= 6 -- Maximum number of PLMNs +maxPNOffset INTEGER ::= 511 -- Maximum number of CDMA2000 PNOffsets +maxPMCH-PerMBSFN INTEGER ::= 15 +maxPSSCH-TxConfig-r14 INTEGER ::= 16 -- Maximum number of PSSCH TX configurations +maxQCI-r13 INTEGER ::= 6 -- Maximum number of QCIs +maxRAT-Capabilities INTEGER ::= 8 -- Maximum number of interworking RATs (incl EUTRA) +maxRE-MapQCL-r11 INTEGER ::= 4 -- Maximum number of PDSCH RE Mapping configurations + -- (per carrier frequency) +maxReportConfigId INTEGER ::= 32 +maxReservationPeriod-r14 INTEGER ::= 16 -- Maximum number of resource reservation periodicities + -- for sidelink V2X communications +maxRSTD-Freq-r10 INTEGER ::= 3 -- Maximum number of frequency layers for RSTD + -- measurement +maxSAI-MBMS-r11 INTEGER ::= 64 -- Maximum number of MBMS service area identities + -- broadcast per carrier frequency +maxSCell-r10 INTEGER ::= 4 -- Maximum number of SCells +maxSCell-r13 INTEGER ::= 31 -- Highest value of extended number range of SCells +maxSC-MTCH-r13 INTEGER ::= 1023 -- Maximum number of SC-MTCHs in one cell +maxSL-CommRxPoolNFreq-r13 INTEGER ::= 32 -- Maximum number of individual sidelink communication + -- Rx resource pools on neighbouring freq +maxSL-CommRxPoolPreconf-v1310 INTEGER ::= 12 -- Maximum number of additional preconfigured + -- sidelink communication Rx resource pool entries +maxSL-TxPool-r12Plus1-r13 INTEGER ::= 5 -- First additional individual sidelink + -- Tx resource pool +maxSL-TxPool-v1310 INTEGER ::= 4 -- Maximum number of additional sidelink + -- Tx resource pool entries +maxSL-TxPool-r13 INTEGER ::= 8 -- Maximum number of individual sidelink + -- Tx resource pools +maxSL-CommTxPoolPreconf-v1310 INTEGER ::= 7 -- Maximum number of additional preconfigured + -- sidelink Tx resource pool entries +maxSL-Dest-r12 INTEGER ::= 16 -- Maximum number of sidelink destinations +maxSL-DiscCells-r13 INTEGER ::= 16 -- Maximum number of cells with similar sidelink + -- configurations +maxSL-DiscPowerClass-r12 INTEGER ::= 3 -- Maximum number of sidelink power classes +maxSL-DiscRxPoolPreconf-r13 INTEGER ::= 16 -- Maximum number of preconfigured sidelink + -- discovery Rx resource pool entries +maxSL-DiscSysInfoReportFreq-r13 INTEGER ::= 8 -- Maximum number of frequencies to include in a + -- SidelinkUEInformation for SI reporting +maxSL-DiscTxPoolPreconf-r13 INTEGER ::= 4 -- Maximum number of preconfigured sidelink + -- discovery Tx resource pool entries +maxSL-GP-r13 INTEGER ::= 8 -- Maximum number of gap patterns that can be requested + -- for a frequency or assigned +maxSL-Prio-r13 INTEGER ::= 8 -- Maximum number of entries in sidelink priority list +maxSL-RxPool-r12 INTEGER ::= 16 -- Maximum number of individual sidelink Rx resource pools +maxSL-SyncConfig-r12 INTEGER ::= 16 -- Maximum number of sidelink Sync configurations +maxSL-TF-IndexPair-r12 INTEGER ::= 64 -- Maximum number of sidelink Time Freq resource index + -- pairs +maxSL-TxPool-r12 INTEGER ::= 4 -- Maximum number of individual sidelink Tx resource pools +maxSL-V2X-RxPool-r14 INTEGER ::= 16 -- Maximum number of RX resource pools for + -- V2X sidelink communication +maxSL-V2X-RxPoolPreconf-r14 INTEGER ::= 16 -- Maximum number of RX resource pools for + -- V2X sidelink communication +maxSL-V2X-TxPool-r14 INTEGER ::= 8 -- Maximum number of TX resource pools for + -- V2X sidelink communication +maxSL-V2X-TxPoolPreconf-r14 INTEGER ::= 8 -- Maximum number of TX resource pools for + -- V2X sidelink communication +maxSL-V2X-SyncConfig-r14 INTEGER ::= 16 -- Maximum number of sidelink Sync configurations + -- for V2X sidelink communication +maxSTAG-r11 INTEGER ::= 3 -- Maximum number of STAGs +maxServCell-r10 INTEGER ::= 5 -- Maximum number of Serving cells +maxServCell-r13 INTEGER ::= 32 -- Highest value of extended number range of Serving cells +maxServiceCount INTEGER ::= 16 -- Maximum number of MBMS services that can be included + -- in an MBMS counting request and response +maxServiceCount-1 INTEGER ::= 15 +maxSessionPerPMCH INTEGER ::= 29 +maxSessionPerPMCH-1 INTEGER ::= 28 +maxSIB INTEGER ::= 32 -- Maximum number of SIBs +maxSIB-1 INTEGER ::= 31 +maxSI-Message INTEGER ::= 32 -- Maximum number of SI messages +maxSimultaneousBands-r10 INTEGER ::= 64 -- Maximum number of simultaneously aggregated bands +maxSubframePatternIDC-r11 INTEGER ::= 8 -- Maximum number of subframe reservation patterns + -- that the UE can simultaneously recommend to the + -- E-UTRAN for use. +maxUTRA-FDD-Carrier INTEGER ::= 16 -- Maximum number of UTRA FDD carrier frequencies +maxUTRA-TDD-Carrier INTEGER ::= 16 -- Maximum number of UTRA TDD carrier frequencies +maxWLAN-Id-r12 INTEGER ::= 16 -- Maximum number of WLAN identifiers +maxWLAN-Bands-r13 INTEGER ::= 8 -- Maximum number of WLAN bands +maxWLAN-Id-r13 INTEGER ::= 32 -- Maximum number of WLAN identifiers +maxWLAN-Channels-r13 INTEGER ::= 16 -- maximum number of WLAN channels used in + -- WLAN-CarrierInfo +maxWLAN-CarrierInfo-r13 INTEGER ::= 8 -- Maximum number of WLAN Carrier Information + + +END + + +PC5-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + TDD-ConfigSL-r12 +FROM EUTRA-RRC-Definitions; + + +SBCCH-SL-BCH-Message ::= SEQUENCE { + message SBCCH-SL-BCH-MessageType +} + +SBCCH-SL-BCH-MessageType ::= MasterInformationBlock-SL + + +MasterInformationBlock-SL ::= SEQUENCE { + sl-Bandwidth-r12 ENUMERATED { + n6, n15, n25, n50, n75, n100}, + tdd-ConfigSL-r12 TDD-ConfigSL-r12, + directFrameNumber-r12 BIT STRING (SIZE (10)), + directSubframeNumber-r12 INTEGER (0..9), + inCoverage-r12 BOOLEAN, + reserved-r12 BIT STRING (SIZE (19)) +} + + + +END + + +NBIOT-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + RRCConnectionReestablishmentReject, + SecurityModeCommand, + SecurityModeComplete, + SecurityModeFailure, + AdditionalSpectrumEmission, + ARFCN-ValueEUTRA-r9, + CellIdentity, + DedicatedInfoNAS, + DRB-Identity, + InitialUE-Identity, + IntraFreqBlackCellList, + IntraFreqNeighCellList, + maxBands, + maxCellBlack, + maxCellInter, + maxFBI2, + maxFreq, + maxMultiBands, + maxPageRec, + maxPLMN-r11, + maxSIB, + maxSIB-1, + NextHopChainingCount, + PagingUE-Identity, + PLMN-Identity, + P-Max, + PowerRampingParameters, + PreambleTransMax, + PhysCellId, + Q-OffsetRange, + Q-QualMin-r9, + Q-RxLevMin, + ReestabUE-Identity, + RegisteredMME, + ReselectionThreshold, + ResumeIdentity-r13, + RRC-TransactionIdentifier, + RSRP-Range, + ShortMAC-I, + S-TMSI, + SystemInformationBlockType16-r11, + SystemInfoValueTagSI-r13, + TimeAlignmentTimer, + TrackingAreaCode +FROM EUTRA-RRC-Definitions; + + +BCCH-BCH-Message-NB ::= SEQUENCE { + message BCCH-BCH-MessageType-NB +} + + +BCCH-BCH-MessageType-NB::= MasterInformationBlock-NB + + + +BCCH-DL-SCH-Message-NB ::= SEQUENCE { + message BCCH-DL-SCH-MessageType-NB +} + +BCCH-DL-SCH-MessageType-NB ::= CHOICE { + c1 CHOICE { + systemInformation-r13 SystemInformation-NB, + systemInformationBlockType1-r13 SystemInformationBlockType1-NB + }, + messageClassExtension SEQUENCE {} +} + + +PCCH-Message-NB ::= SEQUENCE { + message PCCH-MessageType-NB +} + +PCCH-MessageType-NB ::= CHOICE { + c1 CHOICE { + paging-r13 Paging-NB + }, + messageClassExtension SEQUENCE {} +} + + +DL-CCCH-Message-NB ::= SEQUENCE { + message DL-CCCH-MessageType-NB +} + +DL-CCCH-MessageType-NB ::= CHOICE { + c1 CHOICE { + rrcConnectionReestablishment-r13 RRCConnectionReestablishment-NB, + rrcConnectionReestablishmentReject-r13 RRCConnectionReestablishmentReject, + rrcConnectionReject-r13 RRCConnectionReject-NB, + rrcConnectionSetup-r13 RRCConnectionSetup-NB, + spare4 NULL, spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + + +DL-DCCH-Message-NB ::= SEQUENCE { + message DL-DCCH-MessageType-NB +} + +DL-DCCH-MessageType-NB ::= CHOICE { + c1 CHOICE { + dlInformationTransfer-r13 DLInformationTransfer-NB, + rrcConnectionReconfiguration-r13 RRCConnectionReconfiguration-NB, + rrcConnectionRelease-r13 RRCConnectionRelease-NB, + securityModeCommand-r13 SecurityModeCommand, + ueCapabilityEnquiry-r13 UECapabilityEnquiry-NB, + rrcConnectionResume-r13 RRCConnectionResume-NB, + spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + + + +UL-CCCH-Message-NB ::= SEQUENCE { + message UL-CCCH-MessageType-NB +} + +UL-CCCH-MessageType-NB ::= CHOICE { + c1 CHOICE { + rrcConnectionReestablishmentRequest-r13 RRCConnectionReestablishmentRequest-NB, + rrcConnectionRequest-r13 RRCConnectionRequest-NB, + rrcConnectionResumeRequest-r13 RRCConnectionResumeRequest-NB, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + + +UL-DCCH-Message-NB ::= SEQUENCE { + message UL-DCCH-MessageType-NB +} + +UL-DCCH-MessageType-NB ::= CHOICE { + c1 CHOICE { + rrcConnectionReconfigurationComplete-r13 RRCConnectionReconfigurationComplete-NB, + rrcConnectionReestablishmentComplete-r13 RRCConnectionReestablishmentComplete-NB, + rrcConnectionSetupComplete-r13 RRCConnectionSetupComplete-NB, + securityModeComplete-r13 SecurityModeComplete, + securityModeFailure-r13 SecurityModeFailure, + ueCapabilityInformation-r13 UECapabilityInformation-NB, + ulInformationTransfer-r13 ULInformationTransfer-NB, + rrcConnectionResumeComplete-r13 RRCConnectionResumeComplete-NB, + spare8 NULL, spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + + +DLInformationTransfer-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + dlInformationTransfer-r13 DLInformationTransfer-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransfer-NB-r13-IEs ::= SEQUENCE { + dedicatedInfoNAS-r13 DedicatedInfoNAS, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +MasterInformationBlock-NB ::= SEQUENCE { + systemFrameNumber-MSB-r13 BIT STRING (SIZE (4)), + hyperSFN-LSB-r13 BIT STRING (SIZE (2)), + schedulingInfoSIB1-r13 INTEGER (0..15), + systemInfoValueTag-r13 INTEGER (0..31), + ab-Enabled-r13 BOOLEAN, + operationModeInfo-r13 CHOICE { + inband-SamePCI-r13 Inband-SamePCI-NB-r13, + inband-DifferentPCI-r13 Inband-DifferentPCI-NB-r13, + guardband-r13 Guardband-NB-r13, + standalone-r13 Standalone-NB-r13 + }, + spare BIT STRING (SIZE (11)) +} + +ChannelRasterOffset-NB-r13 ::= ENUMERATED {khz-7dot5, khz-2dot5, khz2dot5, khz7dot5} + +Guardband-NB-r13 ::= SEQUENCE { + rasterOffset-r13 ChannelRasterOffset-NB-r13, + spare BIT STRING (SIZE (3)) +} + +Inband-SamePCI-NB-r13 ::= SEQUENCE { + eutra-CRS-SequenceInfo-r13 INTEGER (0..31) +} + +Inband-DifferentPCI-NB-r13 ::= SEQUENCE { + eutra-NumCRS-Ports-r13 ENUMERATED {same, four}, + rasterOffset-r13 ChannelRasterOffset-NB-r13, + spare BIT STRING (SIZE (2)) +} + +Standalone-NB-r13 ::= SEQUENCE { + spare BIT STRING (SIZE (5)) +} + + +Paging-NB ::= SEQUENCE { + pagingRecordList-r13 PagingRecordList-NB-r13 OPTIONAL, -- Need ON + systemInfoModification-r13 ENUMERATED {true} OPTIONAL, -- Need ON + systemInfoModification-eDRX-r13 ENUMERATED {true} OPTIONAL, -- Need ON + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +PagingRecordList-NB-r13 ::= SEQUENCE (SIZE (1..maxPageRec)) OF PagingRecord-NB-r13 + +PagingRecord-NB-r13 ::= SEQUENCE { + ue-Identity-r13 PagingUE-Identity, + ... +} + + +RRCConnectionReconfiguration-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + rrcConnectionReconfiguration-r13 RRCConnectionReconfiguration-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReconfiguration-NB-r13-IEs ::= SEQUENCE { + dedicatedInfoNASList-r13 SEQUENCE (SIZE(1..maxDRB-NB-r13)) OF + DedicatedInfoNAS OPTIONAL, -- Need ON + radioResourceConfigDedicated-r13 RadioResourceConfigDedicated-NB-r13 OPTIONAL, -- Need ON + fullConfig-r13 ENUMERATED {true} OPTIONAL, -- Cond Reestab + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReconfigurationComplete-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcConnectionReconfigurationComplete-r13 RRCConnectionReconfigurationComplete-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReconfigurationComplete-NB-r13-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + + +RRCConnectionReestablishment-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE{ + rrcConnectionReestablishment-r13 RRCConnectionReestablishment-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishment-NB-r13-IEs ::= SEQUENCE { + radioResourceConfigDedicated-r13 RadioResourceConfigDedicated-NB-r13, + nextHopChainingCount-r13 NextHopChainingCount, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReestablishmentComplete-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcConnectionReestablishmentComplete-r13 RRCConnectionReestablishmentComplete-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishmentComplete-NB-r13-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionReestablishmentRequest-NB ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionReestablishmentRequest-r13 + RRCConnectionReestablishmentRequest-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReestablishmentRequest-NB-r13-IEs ::= SEQUENCE { + ue-Identity-r13 ReestabUE-Identity, + reestablishmentCause-r13 ReestablishmentCause-NB-r13, + spare BIT STRING (SIZE (25)) +} + + +ReestablishmentCause-NB-r13 ::= ENUMERATED { + reconfigurationFailure, otherFailure, + spare2, spare1} + + +RRCConnectionReject-NB ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionReject-r13 RRCConnectionReject-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionReject-NB-r13-IEs ::= SEQUENCE { + extendedWaitTime-r13 INTEGER (1..1800), + rrc-SuspendIndication-r13 ENUMERATED {true} OPTIONAL, -- Need ON + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionRelease-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionRelease-r13 RRCConnectionRelease-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionRelease-NB-r13-IEs ::= SEQUENCE { + releaseCause-r13 ReleaseCause-NB-r13, + resumeIdentity-r13 ResumeIdentity-r13 OPTIONAL, -- Need OR + extendedWaitTime-r13 INTEGER (1..1800) OPTIONAL, -- Need ON + redirectedCarrierInfo-r13 RedirectedCarrierInfo-NB-r13 OPTIONAL, -- Need ON + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +ReleaseCause-NB-r13 ::= ENUMERATED {loadBalancingTAUrequired, other, + rrc-Suspend, spare1} + +RedirectedCarrierInfo-NB-r13::= CarrierFreq-NB-r13 + +RRCConnectionRequest-NB ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionRequest-r13 RRCConnectionRequest-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionRequest-NB-r13-IEs ::= SEQUENCE { + ue-Identity-r13 InitialUE-Identity, + establishmentCause-r13 EstablishmentCause-NB-r13, + multiToneSupport-r13 ENUMERATED {true} OPTIONAL, + multiCarrierSupport-r13 ENUMERATED {true} OPTIONAL, + spare BIT STRING (SIZE (22)) +} + + +RRCConnectionResume-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionResume-r13 RRCConnectionResume-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionResume-NB-r13-IEs ::= SEQUENCE { + radioResourceConfigDedicated-r13 RadioResourceConfigDedicated-NB-r13 OPTIONAL, -- Need ON + nextHopChainingCount-r13 NextHopChainingCount, + drb-ContinueROHC-r13 ENUMERATED {true} OPTIONAL, -- Need OP + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionResumeComplete-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcConnectionResumeComplete-r13 RRCConnectionResumeComplete-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionResumeComplete-NB-r13-IEs ::= SEQUENCE { + selectedPLMN-Identity-r13 INTEGER (1..maxPLMN-r11) OPTIONAL, + dedicatedInfoNAS-r13 DedicatedInfoNAS OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionResumeRequest-NB ::= SEQUENCE { + criticalExtensions CHOICE { + rrcConnectionResumeRequest-r13 RRCConnectionResumeRequest-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionResumeRequest-NB-r13-IEs ::= SEQUENCE { + resumeID-r13 ResumeIdentity-r13, + shortResumeMAC-I-r13 ShortMAC-I, + resumeCause-r13 EstablishmentCause-NB-r13, + spare BIT STRING (SIZE (9)) +} + + +RRCConnectionSetup-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + rrcConnectionSetup-r13 RRCConnectionSetup-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionSetup-NB-r13-IEs ::= SEQUENCE { + radioResourceConfigDedicated-r13 RadioResourceConfigDedicated-NB-r13, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +RRCConnectionSetupComplete-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE{ + rrcConnectionSetupComplete-r13 RRCConnectionSetupComplete-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCConnectionSetupComplete-NB-r13-IEs ::= SEQUENCE { + selectedPLMN-Identity-r13 INTEGER (1..maxPLMN-r11), + s-TMSI-r13 S-TMSI OPTIONAL, + registeredMME-r13 RegisteredMME OPTIONAL, + dedicatedInfoNAS-r13 DedicatedInfoNAS, + attachWithoutPDN-Connectivity-r13 ENUMERATED {true} OPTIONAL, + up-CIoT-EPS-Optimisation-r13 ENUMERATED {true} OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SystemInformation-NB ::= SEQUENCE { + criticalExtensions CHOICE { + systemInformation-r13 SystemInformation-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} +SystemInformation-NB-r13-IEs ::= SEQUENCE { + sib-TypeAndInfo-r13 SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + sib2-r13 SystemInformationBlockType2-NB-r13, + sib3-r13 SystemInformationBlockType3-NB-r13, + sib4-r13 SystemInformationBlockType4-NB-r13, + sib5-r13 SystemInformationBlockType5-NB-r13, + sib14-r13 SystemInformationBlockType14-NB-r13, + sib16-r13 SystemInformationBlockType16-NB-r13, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SystemInformationBlockType1-NB ::= SEQUENCE { + hyperSFN-MSB-r13 BIT STRING (SIZE (8)), + cellAccessRelatedInfo-r13 SEQUENCE { + plmn-IdentityList-r13 PLMN-IdentityList-NB-r13, + trackingAreaCode-r13 TrackingAreaCode, + cellIdentity-r13 CellIdentity, + cellBarred-r13 ENUMERATED {barred, notBarred}, + intraFreqReselection-r13 ENUMERATED {allowed, notAllowed} + }, + cellSelectionInfo-r13 SEQUENCE { + q-RxLevMin-r13 Q-RxLevMin, + q-QualMin-r13 Q-QualMin-r9 + }, + p-Max-r13 P-Max OPTIONAL, -- Need OP + freqBandIndicator-r13 FreqBandIndicator-NB-r13, + freqBandInfo-r13 NS-PmaxList-NB-r13 OPTIONAL, -- Need OR + multiBandInfoList-r13 MultiBandInfoList-NB-r13 OPTIONAL, -- Need OR + downlinkBitmap-r13 DL-Bitmap-NB-r13 OPTIONAL, -- Need OP, + eutraControlRegionSize-r13 ENUMERATED {n1, n2, n3} OPTIONAL, -- Cond inband + nrs-CRS-PowerOffset-r13 ENUMERATED {dB-6, dB-4dot77, dB-3, + dB-1dot77, dB0, dB1, + dB1dot23, dB2, dB3, + dB4, dB4dot23, dB5, + dB6, dB7, dB8, + dB9} OPTIONAL, -- Cond inband-SamePCI + schedulingInfoList-r13 SchedulingInfoList-NB-r13, + si-WindowLength-r13 ENUMERATED {ms160, ms320, ms480, ms640, + ms960, ms1280, ms1600, spare1}, + si-RadioFrameOffset-r13 INTEGER (1..15) OPTIONAL, -- Need OP + systemInfoValueTagList-r13 SystemInfoValueTagList-NB-r13 OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +PLMN-IdentityList-NB-r13 ::= SEQUENCE (SIZE (1..maxPLMN-r11)) OF PLMN-IdentityInfo-NB-r13 + +PLMN-IdentityInfo-NB-r13 ::= SEQUENCE { + plmn-Identity-r13 PLMN-Identity, + cellReservedForOperatorUse-r13 ENUMERATED {reserved, notReserved}, + attachWithoutPDN-Connectivity-r13 ENUMERATED {true} OPTIONAL -- Need OP +} + +SchedulingInfoList-NB-r13 ::= SEQUENCE (SIZE (1..maxSI-Message-NB-r13)) OF SchedulingInfo-NB-r13 + +SchedulingInfo-NB-r13::= SEQUENCE { + si-Periodicity-r13 ENUMERATED {rf64, rf128, rf256, rf512, + rf1024, rf2048, rf4096, spare}, + si-RepetitionPattern-r13 ENUMERATED {every2ndRF, every4thRF, + every8thRF, every16thRF}, + sib-MappingInfo-r13 SIB-MappingInfo-NB-r13, + si-TB-r13 ENUMERATED {b56, b120, b208, b256, b328, b440, b552, b680} +} + +SystemInfoValueTagList-NB-r13 ::= SEQUENCE (SIZE (1.. maxSI-Message-NB-r13)) OF + SystemInfoValueTagSI-r13 + +SIB-MappingInfo-NB-r13 ::= SEQUENCE (SIZE (0..maxSIB-1)) OF SIB-Type-NB-r13 + +SIB-Type-NB-r13 ::= ENUMERATED { + sibType3-NB-r13, sibType4-NB-r13, sibType5-NB-r13, + sibType14-NB-r13, sibType16-NB-r13, spare3, spare2, spare1} + + + +UECapabilityEnquiry-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + c1 CHOICE { + ueCapabilityEnquiry-r13 UECapabilityEnquiry-NB-r13-IEs, + spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquiry-NB-r13-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UECapabilityInformation-NB ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE{ + ueCapabilityInformation-r13 UECapabilityInformation-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformation-NB-r13-IEs ::= SEQUENCE { + ue-Capability-Container-r13 UE-Capability-NB-r13, + ue-RadioPagingInfo-r13 UE-RadioPagingInfo-NB-r13, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +ULInformationTransfer-NB ::= SEQUENCE { + criticalExtensions CHOICE { + ulInformationTransfer-r13 ULInformationTransfer-NB-r13-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransfer-NB-r13-IEs ::= SEQUENCE { + dedicatedInfoNAS-r13 DedicatedInfoNAS, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SystemInformationBlockType2-NB-r13 ::= SEQUENCE { + radioResourceConfigCommon-r13 RadioResourceConfigCommonSIB-NB-r13, + ue-TimersAndConstants-r13 UE-TimersAndConstants-NB-r13, + freqInfo-r13 SEQUENCE { + ul-CarrierFreq-r13 CarrierFreq-NB-r13 OPTIONAL,-- Need OP + additionalSpectrumEmission-r13 AdditionalSpectrumEmission + }, + timeAlignmentTimerCommon-r13 TimeAlignmentTimer, + multiBandInfoList-r13 SEQUENCE (SIZE (1..maxMultiBands)) OF AdditionalSpectrumEmission OPTIONAL,-- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +SystemInformationBlockType3-NB-r13 ::= SEQUENCE { + cellReselectionInfoCommon-r13 SEQUENCE { + q-Hyst-r13 ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24 + } + }, + cellReselectionServingFreqInfo-r13 SEQUENCE { + s-NonIntraSearch-r13 ReselectionThreshold + }, + intraFreqCellReselectionInfo-r13 SEQUENCE { + q-RxLevMin-r13 Q-RxLevMin, + q-QualMin-r13 Q-QualMin-r9 OPTIONAL, -- Need OP + p-Max-r13 P-Max OPTIONAL, -- Need OP + s-IntraSearchP-r13 ReselectionThreshold, + t-Reselection-r13 T-Reselection-NB-r13 + }, + freqBandInfo-r13 NS-PmaxList-NB-r13 OPTIONAL, -- Need OR + multiBandInfoList-r13 SEQUENCE (SIZE (1..maxMultiBands)) OF + NS-PmaxList-NB-r13 OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +SystemInformationBlockType4-NB-r13 ::= SEQUENCE { + intraFreqNeighCellList-r13 IntraFreqNeighCellList OPTIONAL, -- Need OR + intraFreqBlackCellList-r13 IntraFreqBlackCellList OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + + +SystemInformationBlockType5-NB-r13 ::= SEQUENCE { + interFreqCarrierFreqList-r13 InterFreqCarrierFreqList-NB-r13, + t-Reselection-r13 T-Reselection-NB-r13, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + + +InterFreqCarrierFreqList-NB-r13 ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-NB-r13 + + +InterFreqCarrierFreqInfo-NB-r13 ::= SEQUENCE { + dl-CarrierFreq-r13 CarrierFreq-NB-r13, + q-RxLevMin-r13 Q-RxLevMin, + q-QualMin-r13 Q-QualMin-r9 OPTIONAL, -- Need OP + p-Max-r13 P-Max OPTIONAL, -- Need OP + q-OffsetFreq-r13 Q-OffsetRange DEFAULT dB0, + interFreqNeighCellList-r13 InterFreqNeighCellList-NB-r13 OPTIONAL, -- Need OR + interFreqBlackCellList-r13 InterFreqBlackCellList-NB-r13 OPTIONAL, -- Need OR + multiBandInfoList-r13 MultiBandInfoList-NB-r13 OPTIONAL, -- Need OR + ... +} + +InterFreqNeighCellList-NB-r13 ::= SEQUENCE (SIZE (1..maxCellInter)) OF PhysCellId + + +InterFreqBlackCellList-NB-r13 ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PhysCellId + + + +SystemInformationBlockType14-NB-r13 ::= SEQUENCE { + ab-Param-r13 CHOICE { + ab-Common-r13 AB-Config-NB-r13, + ab-PerPLMN-List-r13 SEQUENCE (SIZE (1..maxPLMN-r11)) OF AB-ConfigPLMN-NB-r13 + } OPTIONAL, -- Need OR + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +AB-ConfigPLMN-NB-r13 ::= SEQUENCE { + ab-Config-r13 AB-Config-NB-r13 OPTIONAL -- Need OR +} + +AB-Config-NB-r13 ::= SEQUENCE { + ab-Category-r13 ENUMERATED {a, b, c}, + ab-BarringBitmap-r13 BIT STRING (SIZE(10)), + ab-BarringExceptionData-r13 ENUMERATED {true} OPTIONAL, -- Need OP + ab-BarringForSpecialAC-r13 BIT STRING (SIZE(5)) +} + + +SystemInformationBlockType16-NB-r13 ::= SystemInformationBlockType16-r11 + + +CarrierConfigDedicated-NB-r13 ::= SEQUENCE { + dl-CarrierConfig-r13 DL-CarrierConfigDedicated-NB-r13, + ul-CarrierConfig-r13 UL-CarrierConfigDedicated-NB-r13 +} + +DL-CarrierConfigDedicated-NB-r13 ::= SEQUENCE { + dl-CarrierFreq-r13 CarrierFreq-NB-r13, + downlinkBitmapNonAnchor-r13 CHOICE { + useNoBitmap-r13 NULL, + useAnchorBitmap-r13 NULL, + explicitBitmapConfiguration-r13 DL-Bitmap-NB-r13, + spare NULL + } OPTIONAL, -- Need ON + dl-GapNonAnchor-r13 CHOICE { + useNoGap-r13 NULL, + useAnchorGapConfig-r13 NULL, + explicitGapConfiguration-r13 DL-GapConfig-NB-r13, + spare NULL + } OPTIONAL, -- Need ON + inbandCarrierInfo-r13 SEQUENCE { + samePCI-Indicator-r13 CHOICE { + samePCI-r13 SEQUENCE { + indexToMidPRB-r13 INTEGER (-55..54) + }, + differentPCI-r13 SEQUENCE { + eutra-NumCRS-Ports-r13 ENUMERATED {same, four} + } + } OPTIONAL, -- Cond anchor-guardband + eutraControlRegionSize-r13 ENUMERATED {n1, n2, n3} + } OPTIONAL, -- Cond non-anchor-inband + ..., + [[ nrs-PowerOffsetNonAnchor-v1330 ENUMERATED {dB-12, dB-10, dB-8, dB-6, + dB-4, dB-2, dB0, dB3} + OPTIONAL -- Need ON + ]] +} + +UL-CarrierConfigDedicated-NB-r13 ::= SEQUENCE { + ul-CarrierFreq-r13 CarrierFreq-NB-r13 OPTIONAL, -- Need OP + ... +} + + +CarrierFreq-NB-r13 ::= SEQUENCE { + carrierFreq-r13 ARFCN-ValueEUTRA-r9, + carrierFreqOffset-r13 ENUMERATED { + v-10, v-9, v-8, v-7, v-6, v-5, v-4, v-3, v-2, v-1, v-0dot5, + v0, v1, v2, v3, v4, v5, v6, v7, v8, v9 + } OPTIONAL -- Need ON +} + + +DL-Bitmap-NB-r13 ::= CHOICE { + subframePattern10-r13 BIT STRING (SIZE (10)), + subframePattern40-r13 BIT STRING (SIZE (40)) +} + + + +DL-GapConfig-NB-r13 ::= SEQUENCE { + dl-GapThreshold-r13 ENUMERATED {n32, n64, n128, n256}, + dl-GapPeriodicity-r13 ENUMERATED {sf64, sf128, sf256, sf512}, + dl-GapDurationCoeff-r13 ENUMERATED {oneEighth, oneFourth, threeEighth, oneHalf} +} + + +LogicalChannelConfig-NB-r13 ::= SEQUENCE { + priority-r13 INTEGER (1..16) OPTIONAL, -- Cond UL + logicalChannelSR-Prohibit-r13 BOOLEAN OPTIONAL, -- Need ON + ... +} + + +MAC-MainConfig-NB-r13 ::= SEQUENCE { + ul-SCH-Config-r13 SEQUENCE { + periodicBSR-Timer-r13 PeriodicBSR-Timer-NB-r13 OPTIONAL, -- Need ON + retxBSR-Timer-r13 RetxBSR-Timer-NB-r13 + } OPTIONAL, -- Need ON + drx-Config-r13 DRX-Config-NB-r13 OPTIONAL, -- Need ON + timeAlignmentTimerDedicated-r13 TimeAlignmentTimer, + logicalChannelSR-Config-r13 CHOICE { + release NULL, + setup SEQUENCE { + logicalChannelSR-ProhibitTimer-r13 ENUMERATED { + pp2, pp8, pp32, pp128, pp512, + pp1024, pp2048, spare} + } + } OPTIONAL, -- Need ON + ... +} + +PeriodicBSR-Timer-NB-r13 ::= ENUMERATED { + pp2, pp4, pp8, pp16, pp64, pp128, infinity, spare} + +RetxBSR-Timer-NB-r13 ::= ENUMERATED { + pp4, pp16, pp64, pp128, pp256, pp512, infinity, spare} + +DRX-Config-NB-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + onDurationTimer-r13 ENUMERATED { + pp1, pp2, pp3, pp4, pp8, pp16, pp32, spare}, + drx-InactivityTimer-r13 ENUMERATED { + pp0, pp1, pp2, pp3, pp4, pp8, pp16, pp32}, + drx-RetransmissionTimer-r13 ENUMERATED { + pp0, pp1, pp2, pp4, pp6, pp8, pp16, pp24, + pp33, spare7, spare6, spare5, + spare4, spare3, spare2, spare1}, + drx-Cycle-r13 ENUMERATED { + sf256, sf512, sf1024, sf1536, sf2048, sf3072, + sf4096, sf4608, sf6144, sf7680, sf8192, sf9216, + spare4, spare3, spare2, spare1}, + drx-StartOffset-r13 INTEGER (0..255), + drx-ULRetransmissionTimer-r13 ENUMERATED { + pp0, pp1, pp2, pp4, pp6, pp8, pp16, pp24, + pp33, pp40, pp64, pp80, pp96, + pp112, pp128, pp160, pp320} + } +} + + + +NPDCCH-ConfigDedicated-NB-r13 ::= SEQUENCE { + npdcch-NumRepetitions-r13 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, r128, + r256, r512, r1024, r2048, + spare4, spare3, spare2, spare1}, + npdcch-StartSF-USS-r13 ENUMERATED {v1dot5, v2, v4, v8, v16, v32, v48, v64}, + npdcch-Offset-USS-r13 ENUMERATED {zero, oneEighth, oneFourth, threeEighth} +} + + + +NPDSCH-ConfigCommon-NB-r13 ::= SEQUENCE { + nrs-Power-r13 INTEGER (-60..50) +} + + +NPRACH-ConfigSIB-NB-r13 ::= SEQUENCE { + nprach-CP-Length-r13 ENUMERATED {us66dot7, us266dot7}, + rsrp-ThresholdsPrachInfoList-r13 RSRP-ThresholdsNPRACH-InfoList-NB-r13 OPTIONAL, -- need OR + nprach-ParametersList-r13 NPRACH-ParametersList-NB-r13 +} + +NPRACH-ConfigSIB-NB-v1330 ::= SEQUENCE { + nprach-ParametersList-v1330 NPRACH-ParametersList-NB-v1330 +} + +NPRACH-ParametersList-NB-r13 ::= SEQUENCE (SIZE (1.. maxNPRACH-Resources-NB-r13)) OF NPRACH-Parameters-NB-r13 + +NPRACH-ParametersList-NB-v1330 ::= SEQUENCE (SIZE (1.. maxNPRACH-Resources-NB-r13)) OF NPRACH-Parameters-NB-v1330 + +NPRACH-Parameters-NB-r13::= SEQUENCE { + nprach-Periodicity-r13 ENUMERATED {ms40, ms80, ms160, ms240, + ms320, ms640, ms1280, ms2560}, + nprach-StartTime-r13 ENUMERATED {ms8, ms16, ms32, ms64, + ms128, ms256, ms512, ms1024}, + nprach-SubcarrierOffset-r13 ENUMERATED {n0, n12, n24, n36, n2, n18, n34, spare1}, + nprach-NumSubcarriers-r13 ENUMERATED {n12, n24, n36, n48}, + nprach-SubcarrierMSG3-RangeStart-r13 ENUMERATED {zero, oneThird, twoThird, one}, + maxNumPreambleAttemptCE-r13 ENUMERATED {n3, n4, n5, n6, n7, n8, n10, spare1}, + numRepetitionsPerPreambleAttempt-r13 ENUMERATED {n1, n2, n4, n8, n16, n32, n64, n128}, + npdcch-NumRepetitions-RA-r13 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, r128, + r256, r512, r1024, r2048, + spare4, spare3, spare2, spare1}, + npdcch-StartSF-CSS-RA-r13 ENUMERATED {v1dot5, v2, v4, v8, v16, v32, v48, v64}, + npdcch-Offset-RA-r13 ENUMERATED {zero, oneEighth, oneFourth, threeEighth} +} + +NPRACH-Parameters-NB-v1330 ::= SEQUENCE { + nprach-NumCBRA-StartSubcarriers-r13 ENUMERATED {n8, n10, n11, n12, n20, n22, n23, n24, + n32, n34, n35, n36, n40, n44, n46, n48} +} + +RSRP-ThresholdsNPRACH-InfoList-NB-r13 ::= SEQUENCE (SIZE(1..2)) OF RSRP-Range + + +NPUSCH-ConfigCommon-NB-r13 ::= SEQUENCE { + ack-NACK-NumRepetitions-Msg4-r13 SEQUENCE (SIZE(1.. maxNPRACH-Resources-NB-r13)) OF + ACK-NACK-NumRepetitions-NB-r13, + srs-SubframeConfig-r13 ENUMERATED { + sc0, sc1, sc2, sc3, sc4, sc5, sc6, sc7, + sc8, sc9, sc10, sc11, sc12, sc13, sc14, sc15 + } OPTIONAL, -- Need OR + dmrs-Config-r13 SEQUENCE { + threeTone-BaseSequence-r13 INTEGER (0..12) OPTIONAL, -- Need OP + threeTone-CyclicShift-r13 INTEGER (0..2), + sixTone-BaseSequence-r13 INTEGER (0..14) OPTIONAL, -- Need OP + sixTone-CyclicShift-r13 INTEGER (0..3), + twelveTone-BaseSequence-r13 INTEGER (0..30) OPTIONAL -- Need OP + } OPTIONAL, -- Need OR + ul-ReferenceSignalsNPUSCH-r13 UL-ReferenceSignalsNPUSCH-NB-r13 +} + +UL-ReferenceSignalsNPUSCH-NB-r13 ::= SEQUENCE { + groupHoppingEnabled-r13 BOOLEAN, + groupAssignmentNPUSCH-r13 INTEGER (0..29) +} + +NPUSCH-ConfigDedicated-NB-r13 ::= SEQUENCE { + ack-NACK-NumRepetitions-r13 ACK-NACK-NumRepetitions-NB-r13 OPTIONAL, -- Need ON + npusch-AllSymbols-r13 BOOLEAN OPTIONAL, -- Cond SRS + groupHoppingDisabled-r13 ENUMERATED {true} OPTIONAL -- Need OR +} + +ACK-NACK-NumRepetitions-NB-r13 ::= ENUMERATED {r1, r2, r4, r8, r16, r32, r64, r128} + + + +PDCP-Config-NB-r13 ::= SEQUENCE { + discardTimer-r13 ENUMERATED { + ms5120, ms10240, ms20480, ms40960, + ms81920, infinity, spare2, spare1 + } OPTIONAL, -- Cond Setup + headerCompression-r13 CHOICE { + notUsed NULL, + rohc SEQUENCE { + maxCID-r13 INTEGER (1..16383) DEFAULT 15, + profiles-r13 SEQUENCE { + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + ... + } + }, + ... +} + + +PhysicalConfigDedicated-NB-r13 ::= SEQUENCE { + carrierConfigDedicated-r13 CarrierConfigDedicated-NB-r13 OPTIONAL, -- Need ON + npdcch-ConfigDedicated-r13 NPDCCH-ConfigDedicated-NB-r13 OPTIONAL, -- Need ON + npusch-ConfigDedicated-r13 NPUSCH-ConfigDedicated-NB-r13 OPTIONAL, -- Need ON + uplinkPowerControlDedicated-r13 UplinkPowerControlDedicated-NB-r13 OPTIONAL, -- Need ON + ... +} + + + +RACH-ConfigCommon-NB-r13 ::= SEQUENCE { + preambleTransMax-CE-r13 PreambleTransMax, + powerRampingParameters-r13 PowerRampingParameters, + rach-InfoList-r13 RACH-InfoList-NB-r13, + connEstFailOffset-r13 INTEGER (0..15) OPTIONAL, -- Need OP + ... +} + +RACH-InfoList-NB-r13 ::= SEQUENCE (SIZE (1.. maxNPRACH-Resources-NB-r13)) OF RACH-Info-NB-r13 + +RACH-Info-NB-r13 ::= SEQUENCE { + ra-ResponseWindowSize-r13 ENUMERATED { + pp2, pp3, pp4, pp5, pp6, pp7, pp8, pp10}, + mac-ContentionResolutionTimer-r13 ENUMERATED { + pp1, pp2, pp3, pp4, pp8, pp16, pp32, pp64} +} + + +RadioResourceConfigCommonSIB-NB-r13 ::= SEQUENCE { + rach-ConfigCommon-r13 RACH-ConfigCommon-NB-r13, + bcch-Config-r13 BCCH-Config-NB-r13, + pcch-Config-r13 PCCH-Config-NB-r13, + nprach-Config-r13 NPRACH-ConfigSIB-NB-r13, + npdsch-ConfigCommon-r13 NPDSCH-ConfigCommon-NB-r13, + npusch-ConfigCommon-r13 NPUSCH-ConfigCommon-NB-r13, + dl-Gap-r13 DL-GapConfig-NB-r13 OPTIONAL, -- Need OP + uplinkPowerControlCommon-r13 UplinkPowerControlCommon-NB-r13, + ..., + [[ nprach-Config-v1330 NPRACH-ConfigSIB-NB-v1330 OPTIONAL -- Need OR + ]] +} + +BCCH-Config-NB-r13 ::= SEQUENCE { + modificationPeriodCoeff-r13 ENUMERATED {n16, n32, n64, n128} +} + + +PCCH-Config-NB-r13 ::= SEQUENCE { + defaultPagingCycle-r13 ENUMERATED {rf128, rf256, rf512, rf1024}, + nB-r13 ENUMERATED { + fourT, twoT, oneT, halfT, quarterT, one8thT, + one16thT, one32ndT, one64thT, + one128thT, one256thT, one512thT, one1024thT, + spare3, spare2, spare1}, + npdcch-NumRepetitionPaging-r13 ENUMERATED { + r1, r2, r4, r8, r16, r32, r64, r128, + r256, r512, r1024, r2048, + spare4, spare3, spare2, spare1} +} + + +RadioResourceConfigDedicated-NB-r13 ::= SEQUENCE { + srb-ToAddModList-r13 SRB-ToAddModList-NB-r13 OPTIONAL, -- Need ON + drb-ToAddModList-r13 DRB-ToAddModList-NB-r13 OPTIONAL, -- Need ON + drb-ToReleaseList-r13 DRB-ToReleaseList-NB-r13 OPTIONAL, -- Need ON + mac-MainConfig-r13 CHOICE { + explicitValue-r13 MAC-MainConfig-NB-r13, + defaultValue-r13 NULL + } OPTIONAL, -- Need ON + physicalConfigDedicated-r13 PhysicalConfigDedicated-NB-r13 OPTIONAL, -- Need ON + rlf-TimersAndConstants-r13 RLF-TimersAndConstants-NB-r13 OPTIONAL, -- Need ON + ... +} + +SRB-ToAddModList-NB-r13 ::= SEQUENCE (SIZE (1)) OF SRB-ToAddMod-NB-r13 + +SRB-ToAddMod-NB-r13 ::= SEQUENCE { + rlc-Config-r13 CHOICE { + explicitValue RLC-Config-NB-r13, + defaultValue NULL + } OPTIONAL, -- Cond Setup + logicalChannelConfig-r13 CHOICE { + explicitValue LogicalChannelConfig-NB-r13, + defaultValue NULL + } OPTIONAL, -- Cond Setup + ... +} + +DRB-ToAddModList-NB-r13 ::= SEQUENCE (SIZE (1..maxDRB-NB-r13)) OF DRB-ToAddMod-NB-r13 + +DRB-ToAddMod-NB-r13 ::= SEQUENCE { + eps-BearerIdentity-r13 INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup + drb-Identity-r13 DRB-Identity, + pdcp-Config-r13 PDCP-Config-NB-r13 OPTIONAL, -- Cond Setup + rlc-Config-r13 RLC-Config-NB-r13 OPTIONAL, -- Cond Setup + logicalChannelIdentity-r13 INTEGER (3..10) OPTIONAL, -- Cond DRB-Setup + logicalChannelConfig-r13 LogicalChannelConfig-NB-r13 OPTIONAL, -- Cond Setup + ... +} + +DRB-ToReleaseList-NB-r13 ::= SEQUENCE (SIZE (1..maxDRB-NB-r13)) OF DRB-Identity + + +RLC-Config-NB-r13 ::= CHOICE { + am SEQUENCE { + ul-AM-RLC-r13 UL-AM-RLC-NB-r13, + dl-AM-RLC-r13 DL-AM-RLC-NB-r13 + }, + ... +} + + +UL-AM-RLC-NB-r13 ::= SEQUENCE { + t-PollRetransmit-r13 T-PollRetransmit-NB-r13, + maxRetxThreshold-r13 ENUMERATED {t1, t2, t3, t4, t6, t8, t16, t32} +} + +DL-AM-RLC-NB-r13 ::= SEQUENCE { + enableStatusReportSN-Gap-r13 ENUMERATED {true} OPTIONAL +} + +T-PollRetransmit-NB-r13 ::= ENUMERATED { + ms250, ms500, ms1000, ms2000, ms3000, ms4000, + ms6000, ms10000, ms15000, ms25000, ms40000, ms60000, + ms90000, ms120000, ms180000, spare1} + + + + +RLF-TimersAndConstants-NB-r13 ::= CHOICE { + release NULL, + setup SEQUENCE { + t301-r13 ENUMERATED { + ms2500, ms4000, ms6000, ms10000, + ms15000, ms25000, ms40000, ms60000}, + t310-r13 ENUMERATED { + ms0, ms200, ms500, ms1000, ms2000, ms4000, ms8000}, + n310-r13 ENUMERATED { + n1, n2, n3, n4, n6, n8, n10, n20}, + t311-r13 ENUMERATED { + ms1000, ms3000, ms5000, ms10000, ms15000, + ms20000, ms30000}, + n311-r13 ENUMERATED { + n1, n2, n3, n4, n5, n6, n8, n10}, + ... + } +} + + + +UplinkPowerControlCommon-NB-r13 ::= SEQUENCE { + p0-NominalNPUSCH-r13 INTEGER (-126..24), + alpha-r13 ENUMERATED {al0, al04, al05, al06, al07, al08, al09, al1}, + deltaPreambleMsg3-r13 INTEGER (-1..6) +} + +UplinkPowerControlDedicated-NB-r13 ::= SEQUENCE { + p0-UE-NPUSCH-r13 INTEGER (-8..7) +} + + +FreqBandIndicator-NB-r13 ::= INTEGER (1.. maxFBI2) + + +MultiBandInfoList-NB-r13 ::= SEQUENCE (SIZE (1..maxMultiBands)) OF MultiBandInfo-NB-r13 + +MultiBandInfo-NB-r13 ::= SEQUENCE { + freqBandIndicator-r13 FreqBandIndicator-NB-r13 OPTIONAL, -- Need OR + freqBandInfo-r13 NS-PmaxList-NB-r13 OPTIONAL -- Need OR +} + + +NS-PmaxList-NB-r13 ::= SEQUENCE (SIZE (1..maxNS-Pmax-NB-r13)) OF NS-PmaxValue-NB-r13 + +NS-PmaxValue-NB-r13 ::= SEQUENCE { + additionalPmax-r13 P-Max OPTIONAL, -- Need OR + additionalSpectrumEmission-r13 AdditionalSpectrumEmission +} + + +T-Reselection-NB-r13 ::= ENUMERATED {s0, s3, s6, s9, s12, s15, s18, s21} + + +EstablishmentCause-NB-r13 ::= ENUMERATED { + mt-Access, mo-Signalling, mo-Data, mo-ExceptionData, + delayTolerantAccess-v1330, spare3, spare2, spare1} + + +UE-Capability-NB-r13 ::= SEQUENCE { + accessStratumRelease-r13 AccessStratumRelease-NB-r13, + ue-Category-NB-r13 ENUMERATED {nb1} OPTIONAL, + multipleDRB-r13 ENUMERATED {supported} OPTIONAL, + pdcp-Parameters-r13 PDCP-Parameters-NB-r13 OPTIONAL, + phyLayerParameters-r13 PhyLayerParameters-NB-r13, + rf-Parameters-r13 RF-Parameters-NB-r13, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +AccessStratumRelease-NB-r13 ::= ENUMERATED {rel13, spare7, spare6, spare5, spare4, spare3, spare2, spare1, ...} + +PDCP-Parameters-NB-r13 ::= SEQUENCE { + supportedROHC-Profiles-r13 SEQUENCE { + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + maxNumberROHC-ContextSessions-r13 ENUMERATED {cs2, cs4, cs8, cs12} DEFAULT cs2, + ... +} + +PhyLayerParameters-NB-r13 ::= SEQUENCE { + multiTone-r13 ENUMERATED {supported} OPTIONAL, + multiCarrier-r13 ENUMERATED {supported} OPTIONAL + } + +RF-Parameters-NB-r13 ::= SEQUENCE { + supportedBandList-r13 SupportedBandList-NB-r13, + multiNS-Pmax-r13 ENUMERATED {supported} OPTIONAL +} + +SupportedBandList-NB-r13 ::= SEQUENCE (SIZE (1..maxBands)) OF SupportedBand-NB-r13 + +SupportedBand-NB-r13 ::= SEQUENCE { + band-r13 FreqBandIndicator-NB-r13, + powerClassNB-20dBm-r13 ENUMERATED {supported} OPTIONAL +} + + + +UE-RadioPagingInfo-NB-r13 ::= SEQUENCE { + ue-Category-NB-r13 ENUMERATED {nb1} OPTIONAL, + ... +} + + +UE-TimersAndConstants-NB-r13 ::= SEQUENCE { + t300-r13 ENUMERATED { + ms2500, ms4000, ms6000, ms10000, + ms15000, ms25000, ms40000, ms60000}, + t301-r13 ENUMERATED { + ms2500, ms4000, ms6000, ms10000, + ms15000, ms25000, ms40000, ms60000}, + t310-r13 ENUMERATED { + ms0, ms200, ms500, ms1000, ms2000, ms4000, ms8000}, + n310-r13 ENUMERATED { + n1, n2, n3, n4, n6, n8, n10, n20}, + t311-r13 ENUMERATED { + ms1000, ms3000, ms5000, ms10000, ms15000, + ms20000, ms30000}, + n311-r13 ENUMERATED { + n1, n2, n3, n4, n5, n6, n8, n10}, + ... +} + + +maxNPRACH-Resources-NB-r13 INTEGER ::= 3 -- Maximum number of NPRACH resources for NB-IoT +maxDRB-NB-r13 INTEGER ::= 2 -- Maximum number of Data Radio Bearers for NB-IoT +maxNS-Pmax-NB-r13 INTEGER ::= 4 -- Maximum number of NS and P-Max values per band +maxSI-Message-NB-r13 INTEGER ::= 8 -- Maximum number of SI messages for NB-IoT + + +END + + +EUTRA-UE-Variables DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + AbsoluteTimeInfo-r10, + AreaConfiguration-r10, + AreaConfiguration-v1130, + CarrierFreqGERAN, + CellIdentity, + ConnEstFailReport-r11, + SpeedStateScaleFactors, + C-RNTI, + LoggingDuration-r10, + LoggingInterval-r10, + LogMeasInfo-r10, + MeasCSI-RS-Id-r12, + MeasId, + MeasId-v1250, + MeasIdToAddModList, + MeasIdToAddModListExt-r12, + MeasIdToAddModList-v1310, + MeasIdToAddModListExt-v1310, + MeasObjectToAddModList, + MeasObjectToAddModList-v9e0, + MeasObjectToAddModListExt-r13, + MeasScaleFactor-r12, + MobilityStateParameters, + NeighCellConfig, + PhysCellId, + PhysCellIdCDMA2000, + PhysCellIdGERAN, + PhysCellIdUTRA-FDD, + PhysCellIdUTRA-TDD, + PLMN-Identity, + PLMN-IdentityList3-r11, + QuantityConfig, + ReportConfigToAddModList, + RLF-Report-r9, + TargetMBSFN-AreaList-r12, + TraceReference-r10, + VisitedCellInfoList-r12, + maxCellMeas, + maxCSI-RS-Meas-r12, + maxMeasId, + maxMeasId-r12, + UL-DelayConfig-r13, + WLAN-CarrierInfo-r13, + WLAN-Identifiers-r12, + WLAN-Id-List-r13, + WLAN-Status-r13 + + +FROM EUTRA-RRC-Definitions; + + +VarConnEstFailReport-r11 ::= SEQUENCE { + connEstFailReport-r11 ConnEstFailReport-r11, + plmn-Identity-r11 PLMN-Identity +} + + +VarLogMeasConfig-r10 ::= SEQUENCE { + areaConfiguration-r10 AreaConfiguration-r10 OPTIONAL, + loggingDuration-r10 LoggingDuration-r10, + loggingInterval-r10 LoggingInterval-r10 +} + +VarLogMeasConfig-r11 ::= SEQUENCE { + areaConfiguration-r10 AreaConfiguration-r10 OPTIONAL, + areaConfiguration-v1130 AreaConfiguration-v1130 OPTIONAL, + loggingDuration-r10 LoggingDuration-r10, + loggingInterval-r10 LoggingInterval-r10 +} + +VarLogMeasConfig-r12 ::= SEQUENCE { + areaConfiguration-r10 AreaConfiguration-r10 OPTIONAL, + areaConfiguration-v1130 AreaConfiguration-v1130 OPTIONAL, + loggingDuration-r10 LoggingDuration-r10, + loggingInterval-r10 LoggingInterval-r10, + targetMBSFN-AreaList-r12 TargetMBSFN-AreaList-r12 OPTIONAL +} + + +VarLogMeasReport-r10 ::= SEQUENCE { + traceReference-r10 TraceReference-r10, + traceRecordingSessionRef-r10 OCTET STRING (SIZE (2)), + tce-Id-r10 OCTET STRING (SIZE (1)), + plmn-Identity-r10 PLMN-Identity, + absoluteTimeInfo-r10 AbsoluteTimeInfo-r10, + logMeasInfoList-r10 LogMeasInfoList2-r10 +} + +VarLogMeasReport-r11 ::= SEQUENCE { + traceReference-r10 TraceReference-r10, + traceRecordingSessionRef-r10 OCTET STRING (SIZE (2)), + tce-Id-r10 OCTET STRING (SIZE (1)), + plmn-IdentityList-r11 PLMN-IdentityList3-r11, + absoluteTimeInfo-r10 AbsoluteTimeInfo-r10, + logMeasInfoList-r10 LogMeasInfoList2-r10 +} + +LogMeasInfoList2-r10 ::= SEQUENCE (SIZE (1..maxLogMeas-r10)) OF LogMeasInfo-r10 + + +VarMeasConfig ::= SEQUENCE { + -- Measurement identities + measIdList MeasIdToAddModList OPTIONAL, + measIdListExt-r12 MeasIdToAddModListExt-r12 OPTIONAL, + measIdList-v1310 MeasIdToAddModList-v1310 OPTIONAL, + measIdListExt-v1310 MeasIdToAddModListExt-v1310 OPTIONAL, + -- Measurement objects + measObjectList MeasObjectToAddModList OPTIONAL, + measObjectListExt-r13 MeasObjectToAddModListExt-r13 OPTIONAL, + measObjectList-v9i0 MeasObjectToAddModList-v9e0 OPTIONAL, + -- Reporting configurations + reportConfigList ReportConfigToAddModList OPTIONAL, + -- Other parameters + quantityConfig QuantityConfig OPTIONAL, + measScaleFactor-r12 MeasScaleFactor-r12 OPTIONAL, + s-Measure INTEGER (-140..-44) OPTIONAL, + speedStatePars CHOICE { + release NULL, + setup SEQUENCE { + mobilityStateParameters MobilityStateParameters, + timeToTrigger-SF SpeedStateScaleFactors + } + } OPTIONAL, + allowInterruptions-r11 BOOLEAN OPTIONAL +} + + +VarMeasReportList ::= SEQUENCE (SIZE (1..maxMeasId)) OF VarMeasReport +VarMeasReportList-r12 ::= SEQUENCE (SIZE (1..maxMeasId-r12)) OF VarMeasReport + +VarMeasReport ::= SEQUENCE { + -- List of measurement that have been triggered + measId MeasId, + measId-v1250 MeasId-v1250 OPTIONAL, + cellsTriggeredList CellsTriggeredList OPTIONAL, + csi-RS-TriggeredList-r12 CSI-RS-TriggeredList-r12 OPTIONAL, + numberOfReportsSent INTEGER +} + +CellsTriggeredList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CHOICE { + physCellIdEUTRA PhysCellId, + physCellIdUTRA CHOICE { + fdd PhysCellIdUTRA-FDD, + tdd PhysCellIdUTRA-TDD + }, + physCellIdGERAN SEQUENCE { + carrierFreq CarrierFreqGERAN, + physCellId PhysCellIdGERAN + }, + physCellIdCDMA2000 PhysCellIdCDMA2000, + wlan-Identifiers-r13 WLAN-Identifiers-r12 +} + +CSI-RS-TriggeredList-r12 ::= SEQUENCE (SIZE (1..maxCSI-RS-Meas-r12)) OF MeasCSI-RS-Id-r12 + +VarMobilityHistoryReport-r12 ::= VisitedCellInfoList-r12 + + +VarRLF-Report-r10 ::= SEQUENCE { + rlf-Report-r10 RLF-Report-r9, + plmn-Identity-r10 PLMN-Identity +} + +VarRLF-Report-r11 ::= SEQUENCE { + rlf-Report-r10 RLF-Report-r9, + plmn-IdentityList-r11 PLMN-IdentityList3-r11 +} + + +VarShortMAC-Input ::= SEQUENCE { + cellIdentity CellIdentity, + physCellId PhysCellId, + c-RNTI C-RNTI +} + +VarShortResumeMAC-Input-r13 ::= SEQUENCE { + cellIdentity-r13 CellIdentity, + physCellId-r13 PhysCellId, + c-RNTI-r13 C-RNTI, + resumeDiscriminator-r13 BIT STRING(SIZE(1)) +} + + +VarWLAN-MobilityConfig ::= SEQUENCE { + wlan-MobilitySet-r13 WLAN-Id-List-r13 OPTIONAL, + successReportRequested ENUMERATED {true} OPTIONAL +} + + +VarWLAN-Status-r13 ::= SEQUENCE { + status-r13 WLAN-Status-r13 +} + + +maxLogMeas-r10 INTEGER ::= 4060-- Maximum number of logged measurement entries + -- that can be stored by the UE + + +END + + +NBIOT-UE-Variables DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + VarShortMAC-Input, + VarShortResumeMAC-Input-r13 + +FROM EUTRA-UE-Variables; + +VarShortMAC-Input-NB-r13 ::= VarShortMAC-Input + +VarShortResumeMAC-Input-NB-r13 ::= VarShortResumeMAC-Input-r13 + + + +END + + +EUTRA-Sidelink-Preconf DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + AdditionalSpectrumEmission, + ARFCN-ValueEUTRA-r9, + FilterCoefficient, + maxFreq, + maxSL-TxPool-r12, + maxSL-CommRxPoolPreconf-v1310, + maxSL-CommTxPoolPreconf-v1310, + maxSL-DiscRxPoolPreconf-r13, + maxSL-DiscTxPoolPreconf-r13, + maxSL-V2X-RxPoolPreconf-r14, + maxSL-V2X-TxPoolPreconf-r14, + P-Max, + ReselectionInfoRelay-r13, + SL-CommTxPoolSensingConfig-r14, + SL-CP-Len-r12, + SL-HoppingConfigComm-r12, + SL-OffsetIndicator-r12, + SL-OffsetIndicatorSync-r12, + SL-OffsetIndicatorSync-v14xy, + SL-PeriodComm-r12, + RSRP-RangeSL3-r12, + SL-PriorityList-r13, + SL-TF-ResourceConfig-r12, + SL-TRPT-Subset-r12, + SL-TxParameters-r12, + SL-ZoneConfig-r14, + P0-SL-r12, + TDD-ConfigSL-r12, + SubframeBitmapSL-r14 +FROM EUTRA-RRC-Definitions; + + +SL-Preconfiguration-r12 ::= SEQUENCE { + preconfigGeneral-r12 SL-PreconfigGeneral-r12, + preconfigSync-r12 SL-PreconfigSync-r12, + preconfigComm-r12 SL-PreconfigCommPoolList4-r12, + ..., + [[ preconfigComm-v1310 SEQUENCE { + commRxPoolList-r13 SL-PreconfigCommRxPoolList-r13, + commTxPoolList-r13 SL-PreconfigCommTxPoolList-r13 OPTIONAL + } OPTIONAL, + preconfigDisc-r13 SEQUENCE { + discRxPoolList-r13 SL-PreconfigDiscRxPoolList-r13, + discTxPoolList-r13 SL-PreconfigDiscTxPoolList-r13 OPTIONAL + } OPTIONAL, + preconfigRelay-r13 SL-PreconfigRelay-r13 OPTIONAL + ]] + +} + +SL-PreconfigGeneral-r12 ::= SEQUENCE { + -- PDCP configuration + rohc-Profiles-r12 SEQUENCE { + profile0x0001-r12 BOOLEAN, + profile0x0002-r12 BOOLEAN, + profile0x0004-r12 BOOLEAN, + profile0x0006-r12 BOOLEAN, + profile0x0101-r12 BOOLEAN, + profile0x0102-r12 BOOLEAN, + profile0x0104-r12 BOOLEAN + }, + -- Physical configuration + carrierFreq-r12 ARFCN-ValueEUTRA-r9, + maxTxPower-r12 P-Max, + additionalSpectrumEmission-r12 AdditionalSpectrumEmission, + sl-bandwidth-r12 ENUMERATED {n6, n15, n25, n50, n75, n100}, + tdd-ConfigSL-r12 TDD-ConfigSL-r12, + reserved-r12 BIT STRING (SIZE (19)), + ... +} + +SL-PreconfigSync-r12 ::= SEQUENCE { + syncCP-Len-r12 SL-CP-Len-r12, + syncOffsetIndicator1-r12 SL-OffsetIndicatorSync-r12, + syncOffsetIndicator2-r12 SL-OffsetIndicatorSync-r12, + syncTxParameters-r12 P0-SL-r12, + syncTxThreshOoC-r12 RSRP-RangeSL3-r12, + filterCoefficient-r12 FilterCoefficient, + syncRefMinHyst-r12 ENUMERATED {dB0, dB3, dB6, dB9, dB12}, + syncRefDiffHyst-r12 ENUMERATED {dB0, dB3, dB6, dB9, dB12, dBinf}, + ..., + [[ syncTxPeriodic-r13 ENUMERATED {true} OPTIONAL + ]], + [[ syncOffsetIndicator1-v14xy SL-OffsetIndicatorSync-v14xy OPTIONAL, + syncOffsetIndicator2-v14xy SL-OffsetIndicatorSync-v14xy OPTIONAL + ]] +} + +SL-PreconfigCommPoolList4-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF SL-PreconfigCommPool-r12 + +SL-PreconfigCommRxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-CommRxPoolPreconf-v1310)) OF SL-PreconfigCommPool-r12 + +SL-PreconfigCommTxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-CommTxPoolPreconf-v1310)) OF SL-PreconfigCommPool-r12 + +SL-PreconfigCommPool-r12 ::= SEQUENCE { +-- This IE is same as SL-CommResourcePool with rxParametersNCell absent + sc-CP-Len-r12 SL-CP-Len-r12, + sc-Period-r12 SL-PeriodComm-r12, + sc-TF-ResourceConfig-r12 SL-TF-ResourceConfig-r12, + sc-TxParameters-r12 P0-SL-r12, + data-CP-Len-r12 SL-CP-Len-r12, + data-TF-ResourceConfig-r12 SL-TF-ResourceConfig-r12, + dataHoppingConfig-r12 SL-HoppingConfigComm-r12, + dataTxParameters-r12 P0-SL-r12, + trpt-Subset-r12 SL-TRPT-Subset-r12, + ..., + [[ priorityList-r13 SL-PriorityList-r13 OPTIONAL -- For Tx + ]] +} + +SL-PreconfigDiscRxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-DiscRxPoolPreconf-r13)) OF SL-PreconfigDiscPool-r13 + +SL-PreconfigDiscTxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-DiscTxPoolPreconf-r13)) OF SL-PreconfigDiscPool-r13 + +SL-PreconfigDiscPool-r13 ::= SEQUENCE { +-- This IE is same as SL-DiscResourcePool with rxParameters absent + cp-Len-r13 SL-CP-Len-r12, + discPeriod-r13 ENUMERATED {rf4, rf6, rf7, rf8, rf12, rf14, rf16, rf24, rf28, + rf32, rf64, rf128, rf256, rf512, rf1024, spare}, + numRetx-r13 INTEGER (0..3), + numRepetition-r13 INTEGER (1..50), + tf-ResourceConfig-r13 SL-TF-ResourceConfig-r12, + txParameters-r13 SEQUENCE { + txParametersGeneral-r13 P0-SL-r12, + txProbability-r13 ENUMERATED {p25, p50, p75, p100} + } OPTIONAL, + ... +} + +SL-PreconfigRelay-r13 ::= SEQUENCE { + reselectionInfoOoC-r13 ReselectionInfoRelay-r13 +} + + +SL-V2X-Preconfiguration-r14 ::= SEQUENCE (SIZE (1..maxFreq)) OF SL-V2X-PreconfigFreqInfo-r14 + +SL-V2X-PreconfigFreqInfo-r14 ::= SEQUENCE { + v2x-CommPreconfigGeneral-r14 SL-PreconfigGeneral-r12, + v2x-CommPreconfigSync-r14 SL-PreconfigSync-r12, + v2x-CommRxPoolList-r14 SL-PreconfigV2X-RxPoolList-r14, + v2x-CommTxPoolList-r14 SL-PreconfigV2X-TxPoolList-r14, + v2x-ResourceSelectionConfig-r14 SL-CommTxPoolSensingConfig-r14 OPTIONAL, + zoneConfig-r14 SL-ZoneConfig-r14 OPTIONAL, + ... +} + +SL-PreconfigV2X-RxPoolList-r14 ::= SEQUENCE (SIZE (1..maxSL-V2X-RxPoolPreconf-r14)) OF SL-V2X-PreconfigCommPool-r14 + +SL-PreconfigV2X-TxPoolList-r14 ::= SEQUENCE (SIZE (1..maxSL-V2X-TxPoolPreconf-r14)) OF SL-V2X-PreconfigCommPool-r14 + +SL-V2X-PreconfigCommPool-r14 ::= SEQUENCE { +-- This IE is same as SL-V2X-CommResourcePool with rxParametersNCell absent + sl-OffsetIndicator-r14 SL-OffsetIndicator-r12 OPTIONAL, + sl-Subframe-r14 SubframeBitmapSL-r14, + adjacencyPSCCH-PSSCH-r14 BOOLEAN, + sizeSubchannel-r14 ENUMERATED { + n4, n5, n6, n8, n9, n10, n12, n15, n16, n18, n20, n25, n30, + n48, n50, n72, n75, n96, n100, spare13, spare12, spare11, + spare10, spare9, spare8, spare7, spare6, spare5, spare4, + spare3, spare2, spare1}, + numSubchannel-r14 ENUMERATED {n1, n3, n5, n10, n15, n20, spare2, spare1}, + startRB-Subchannel-r14 INTEGER (0..99), + startRB-PSCCH-Pool-r14 INTEGER (0..99) OPTIONAL, + dataTxParameters-r14 SL-TxParameters-r12 OPTIONAL, + zoneID-r14 INTEGER (0..7) OPTIONAL, + ... +} + +END + + +EUTRA-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + AntennaInfoCommon, + AntennaInfoDedicated-v10i0, + ARFCN-ValueEUTRA, + ARFCN-ValueEUTRA-v9e0, + ARFCN-ValueEUTRA-r9, + CellIdentity, + C-RNTI, + DL-DCCH-Message, + DRB-Identity, + DRB-ToReleaseList, + FreqBandIndicator-r11, + InDeviceCoexIndication-r11, + MasterInformationBlock, + maxBands, + maxFreq, + maxDRB, + maxSCell-r10, + maxSCell-r13, + maxServCell-r10, + maxServCell-r13, + MBMSInterestIndication-r11, + MeasConfig, + MeasGapConfig, + MeasResultForRSSI-r13, + OtherConfig-r9, + PhysCellId, + P-Max, + PowerCoordinationInfo-r12, + SidelinkUEInformation-r12, + SL-CommConfig-r12, + SL-DiscConfig-r12, + RadioResourceConfigDedicated, + RCLWI-Configuration-r13, + RSRP-Range, + RSRQ-Range, + RSRQ-Range-v1250, + RS-SINR-Range-r13, + SCellToAddModList-r10, + SCellToAddModListExt-r13, + SCG-ConfigPartSCG-r12, + SecurityAlgorithmConfig, + SCellIndex-r10, + SCellIndex-r13, + SCellToReleaseList-r10, + SCellToReleaseListExt-r13, + ServCellIndex-r10, + ServCellIndex-r13, + ShortMAC-I, + MeasResultSSTD-r13, + SL-V2X-ConfigDedicated-r14, + SystemInformationBlockType1, + SystemInformationBlockType1-v890-IEs, + SystemInformationBlockType2, + UEAssistanceInformation-r11, + UECapabilityInformation, + UE-CapabilityRAT-ContainerList, + UE-RadioPagingInfo-r12, + WLANConnectionStatusReport-r13, + WLAN-OffloadConfig-r12 +FROM EUTRA-RRC-Definitions; + + +HandoverCommand ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverCommand-r8 HandoverCommand-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverCommand-r8-IEs ::= SEQUENCE { + handoverCommandMessage OCTET STRING (CONTAINING DL-DCCH-Message), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +HandoverPreparationInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverPreparationInformation-r8 HandoverPreparationInformation-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverPreparationInformation-r8-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo UE-CapabilityRAT-ContainerList, + as-Config AS-Config OPTIONAL, -- Cond HO + rrm-Config RRM-Config OPTIONAL, + as-Context AS-Context OPTIONAL, -- Cond HO + nonCriticalExtension HandoverPreparationInformation-v920-IEs OPTIONAL +} + +HandoverPreparationInformation-v920-IEs ::= SEQUENCE { + ue-ConfigRelease-r9 ENUMERATED { + rel9, rel10, rel11, rel12, v10j0, v11e0, + v1280, rel13, ...} OPTIONAL, -- Cond HO2 + nonCriticalExtension HandoverPreparationInformation-v9d0-IEs OPTIONAL +} + +HandoverPreparationInformation-v9d0-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING (CONTAINING HandoverPreparationInformation-v9j0-IEs) OPTIONAL, + nonCriticalExtension HandoverPreparationInformation-v9e0-IEs OPTIONAL +} + +-- Late non-critical extensions: +HandoverPreparationInformation-v9j0-IEs ::= SEQUENCE { + -- Following field is only for pre REL-10 late non-critical extensions + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension HandoverPreparationInformation-v10j0-IEs OPTIONAL +} + +HandoverPreparationInformation-v10j0-IEs ::= SEQUENCE { + as-Config-v10j0 AS-Config-v10j0 OPTIONAL, + -- Following field is only for late non-critical extensions from REL-10 + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non-critical extensions: +HandoverPreparationInformation-v9e0-IEs ::= SEQUENCE { + as-Config-v9e0 AS-Config-v9e0 OPTIONAL, -- Cond HO2 + nonCriticalExtension HandoverPreparationInformation-v1130-IEs OPTIONAL +} + +HandoverPreparationInformation-v1130-IEs ::= SEQUENCE { + as-Context-v1130 AS-Context-v1130 OPTIONAL, -- Cond HO2 + nonCriticalExtension HandoverPreparationInformation-v1250-IEs OPTIONAL +} + +HandoverPreparationInformation-v1250-IEs ::= SEQUENCE { + ue-SupportedEARFCN-r12 ARFCN-ValueEUTRA-r9 OPTIONAL, -- Cond HO3 + as-Config-v1250 AS-Config-v1250 OPTIONAL, -- Cond HO2 + nonCriticalExtension HandoverPreparationInformation-v1320-IEs OPTIONAL +} + +HandoverPreparationInformation-v1320-IEs ::= SEQUENCE { + as-Config-v1320 AS-Config-v1320 OPTIONAL, -- Cond HO2 + as-Context-v1320 AS-Context-v1320 OPTIONAL, -- Cond HO2 + nonCriticalExtension HandoverPreparationInformation-v14x0-IEs OPTIONAL +} + +HandoverPreparationInformation-v14x0-IEs ::= SEQUENCE { + as-Config-v14x0 AS-Config-v14x0 OPTIONAL, -- Cond HO2 + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SCG-Config-r12 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + scg-Config-r12 SCG-Config-r12-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCG-Config-r12-IEs ::= SEQUENCE { + scg-RadioConfig-r12 SCG-ConfigPartSCG-r12 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +SCG-ConfigInfo-r12 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + scg-ConfigInfo-r12 SCG-ConfigInfo-r12-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCG-ConfigInfo-r12-IEs ::= SEQUENCE { + radioResourceConfigDedMCG-r12 RadioResourceConfigDedicated OPTIONAL, + sCellToAddModListMCG-r12 SCellToAddModList-r10 OPTIONAL, + measGapConfig-r12 MeasGapConfig OPTIONAL, + powerCoordinationInfo-r12 PowerCoordinationInfo-r12 OPTIONAL, + scg-RadioConfig-r12 SCG-ConfigPartSCG-r12 OPTIONAL, + eutra-CapabilityInfo-r12 OCTET STRING (CONTAINING UECapabilityInformation) OPTIONAL, + scg-ConfigRestrictInfo-r12 SCG-ConfigRestrictInfo-r12 OPTIONAL, + mbmsInterestIndication-r12 OCTET STRING (CONTAINING + MBMSInterestIndication-r11) OPTIONAL, + measResultServCellListSCG-r12 MeasResultServCellListSCG-r12 OPTIONAL, + drb-ToAddModListSCG-r12 DRB-InfoListSCG-r12 OPTIONAL, + drb-ToReleaseListSCG-r12 DRB-ToReleaseList OPTIONAL, + sCellToAddModListSCG-r12 SCellToAddModListSCG-r12 OPTIONAL, + sCellToReleaseListSCG-r12 SCellToReleaseList-r10 OPTIONAL, + p-Max-r12 P-Max OPTIONAL, + nonCriticalExtension SCG-ConfigInfo-v1310-IEs OPTIONAL +} + +SCG-ConfigInfo-v1310-IEs ::= SEQUENCE { + measResultSSTD-r13 MeasResultSSTD-r13 OPTIONAL, sCellToAddModListMCG-Ext-r13 SCellToAddModListExt-r13 OPTIONAL, + measResultServCellListSCG-Ext-r13 MeasResultServCellListSCG-Ext-r13 OPTIONAL, + sCellToAddModListSCG-Ext-r13 SCellToAddModListSCG-Ext-r13 OPTIONAL, + sCellToReleaseListSCG-Ext-r13 SCellToReleaseListExt-r13 OPTIONAL, + nonCriticalExtension SCG-ConfigInfo-v1330-IEs OPTIONAL +} + +SCG-ConfigInfo-v1330-IEs ::= SEQUENCE { + measResultListRSSI-SCG-r13 MeasResultListRSSI-SCG-r13 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +DRB-InfoListSCG-r12 ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-InfoSCG-r12 + +DRB-InfoSCG-r12 ::= SEQUENCE { + eps-BearerIdentity-r12 INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup + drb-Identity-r12 DRB-Identity, + drb-Type-r12 ENUMERATED {split, scg} OPTIONAL, -- Cond DRB-Setup + ... +} + +SCellToAddModListSCG-r12 ::= SEQUENCE (SIZE (1..maxSCell-r10)) OF Cell-ToAddMod-r12 + +SCellToAddModListSCG-Ext-r13 ::= SEQUENCE (SIZE (1..maxSCell-r13)) OF Cell-ToAddMod-r12 + +Cell-ToAddMod-r12 ::= SEQUENCE { + sCellIndex-r12 SCellIndex-r10, + cellIdentification-r12 SEQUENCE { + physCellId-r12 PhysCellId, + dl-CarrierFreq-r12 ARFCN-ValueEUTRA-r9 + } OPTIONAL, -- Cond SCellAdd + measResultCellToAdd-r12 SEQUENCE { + rsrpResult-r12 RSRP-Range, + rsrqResult-r12 RSRQ-Range + } OPTIONAL, -- Cond SCellAdd2 + ..., + [[ sCellIndex-r13 SCellIndex-r13 OPTIONAL, + measResultCellToAdd-v1310 SEQUENCE { + rs-sinr-Result-r13 RS-SINR-Range-r13 + } OPTIONAL -- Cond SCellAdd2 + ]] +} + +MeasResultServCellListSCG-r12 ::= SEQUENCE (SIZE (1..maxServCell-r10)) OF MeasResultServCellSCG-r12 + +MeasResultServCellListSCG-Ext-r13 ::= SEQUENCE (SIZE (1..maxServCell-r13)) OF MeasResultServCellSCG-r12 + +MeasResultServCellSCG-r12 ::= SEQUENCE { + servCellId-r12 ServCellIndex-r10, + measResultSCell-r12 SEQUENCE { + rsrpResultSCell-r12 RSRP-Range, + rsrqResultSCell-r12 RSRQ-Range + }, + ..., + [[ servCellId-r13 ServCellIndex-r13 OPTIONAL, + measResultSCell-v1310 SEQUENCE { + rs-sinr-ResultSCell-r13 RS-SINR-Range-r13 + } OPTIONAL + ]] +} + +MeasResultListRSSI-SCG-r13 ::= SEQUENCE (SIZE (1..maxServCell-r13)) OF MeasResultRSSI-SCG-r13 + +MeasResultRSSI-SCG-r13 ::= SEQUENCE { + servCellId-r13 ServCellIndex-r13, + measResultForRSSI-r13 MeasResultForRSSI-r13 +} + +SCG-ConfigRestrictInfo-r12 ::= SEQUENCE { + maxSCH-TB-BitsDL-r12 INTEGER (1..100), + maxSCH-TB-BitsUL-r12 INTEGER (1..100) +} + + +UEPagingCoverageInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + uePagingCoverageInformation-r13 UEPagingCoverageInformation-r13-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEPagingCoverageInformation-r13-IEs ::= SEQUENCE { + mpdcch-NumRepetition-r13 INTEGER (1..256) OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UERadioAccessCapabilityInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioAccessCapabilityInformation-r8 + UERadioAccessCapabilityInformation-r8-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioAccessCapabilityInformation-r8-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo OCTET STRING (CONTAINING UECapabilityInformation), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UERadioPagingInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioPagingInformation-r12 UERadioPagingInformation-r12-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioPagingInformation-r12-IEs ::= SEQUENCE { + ue-RadioPagingInfo-r12 OCTET STRING (CONTAINING UE-RadioPagingInfo-r12), + nonCriticalExtension UERadioPagingInformation-v1310-IEs OPTIONAL +} + +UERadioPagingInformation-v1310-IEs ::= SEQUENCE { + supportedBandListEUTRAForPaging-r13 SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicator-r11 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL + +} + + +AS-Config ::= SEQUENCE { + sourceMeasConfig MeasConfig, + sourceRadioResourceConfig RadioResourceConfigDedicated, + sourceSecurityAlgorithmConfig SecurityAlgorithmConfig, + sourceUE-Identity C-RNTI, + sourceMasterInformationBlock MasterInformationBlock, + sourceSystemInformationBlockType1 SystemInformationBlockType1(WITH COMPONENTS + {..., nonCriticalExtension ABSENT}), + sourceSystemInformationBlockType2 SystemInformationBlockType2, + antennaInfoCommon AntennaInfoCommon, + sourceDl-CarrierFreq ARFCN-ValueEUTRA, + ..., + [[ sourceSystemInformationBlockType1Ext OCTET STRING (CONTAINING + SystemInformationBlockType1-v890-IEs) OPTIONAL, + sourceOtherConfig-r9 OtherConfig-r9 + -- sourceOtherConfig-r9 should have been optional. A target eNB compliant with this transfer + -- syntax should support receiving an AS-Config not including this extension addition group + -- e.g. from a legacy source eNB + ]], + [[ sourceSCellConfigList-r10 SCellToAddModList-r10 OPTIONAL + ]], + [[ sourceConfigSCG-r12 SCG-Config-r12 OPTIONAL + ]] +} + +AS-Config-v9e0 ::= SEQUENCE { + sourceDl-CarrierFreq-v9e0 ARFCN-ValueEUTRA-v9e0 +} + +AS-Config-v10j0 ::= SEQUENCE { + antennaInfoDedicatedPCell-v10i0 AntennaInfoDedicated-v10i0 OPTIONAL +} + +AS-Config-v1250 ::= SEQUENCE { + sourceWlan-OffloadConfig-r12 WLAN-OffloadConfig-r12 OPTIONAL, + sourceSL-CommConfig-r12 SL-CommConfig-r12 OPTIONAL, + sourceSL-DiscConfig-r12 SL-DiscConfig-r12 OPTIONAL +} + +AS-Config-v1320 ::= SEQUENCE { + sourceSCellConfigList-r13 SCellToAddModListExt-r13 OPTIONAL, + sourceRCLWI-Configuration-r13 RCLWI-Configuration-r13 OPTIONAL +} + +AS-Config-v14x0 ::= SEQUENCE { + sourceSL-V2X-CommConfig-r14 SL-V2X-ConfigDedicated-r14 OPTIONAL +} + + +AS-Context ::= SEQUENCE { + reestablishmentInfo ReestablishmentInfo OPTIONAL -- Cond HO +} + +AS-Context-v1130 ::= SEQUENCE { + idc-Indication-r11 OCTET STRING (CONTAINING + InDeviceCoexIndication-r11) OPTIONAL, -- Cond HO2 + mbmsInterestIndication-r11 OCTET STRING (CONTAINING + MBMSInterestIndication-r11) OPTIONAL, -- Cond HO2 + powerPrefIndication-r11 OCTET STRING (CONTAINING + UEAssistanceInformation-r11) OPTIONAL, -- Cond HO2 + ..., + [[ sidelinkUEInformation-r12 OCTET STRING (CONTAINING + SidelinkUEInformation-r12) OPTIONAL -- Cond HO2 + ]] +} + +AS-Context-v1320 ::= SEQUENCE { + wlanConnectionStatusReport-r13 OCTET STRING (CONTAINING + WLANConnectionStatusReport-r13) OPTIONAL -- Cond HO2 +} + + +ReestablishmentInfo ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellShortMAC-I ShortMAC-I, + additionalReestabInfoList AdditionalReestabInfoList OPTIONAL, + ... +} + +AdditionalReestabInfoList ::= SEQUENCE ( SIZE (1..maxReestabInfo) ) OF AdditionalReestabInfo + +AdditionalReestabInfo ::= SEQUENCE{ + cellIdentity CellIdentity, + key-eNodeB-Star Key-eNodeB-Star, + shortMAC-I ShortMAC-I +} + +Key-eNodeB-Star ::= BIT STRING (SIZE (256)) + + +RRM-Config ::= SEQUENCE { + ue-InactiveTime ENUMERATED { + s1, s2, s3, s5, s7, s10, s15, s20, + s25, s30, s40, s50, min1, min1s20c, min1s40, + min2, min2s30, min3, min3s30, min4, min5, min6, + min7, min8, min9, min10, min12, min14, min17, min20, + min24, min28, min33, min38, min44, min50, hr1, + hr1min30, hr2, hr2min30, hr3, hr3min30, hr4, hr5, hr6, + hr8, hr10, hr13, hr16, hr20, day1, day1hr12, day2, + day2hr12, day3, day4, day5, day7, day10, day14, day19, + day24, day30, dayMoreThan30} OPTIONAL, + ..., + [[ candidateCellInfoList-r10 CandidateCellInfoList-r10 OPTIONAL + ]] +} + +CandidateCellInfoList-r10 ::= SEQUENCE (SIZE (1..maxFreq)) OF CandidateCellInfo-r10 + +CandidateCellInfo-r10 ::= SEQUENCE { + -- cellIdentification + physCellId-r10 PhysCellId, + dl-CarrierFreq-r10 ARFCN-ValueEUTRA, + -- available measurement results + rsrpResult-r10 RSRP-Range OPTIONAL, + rsrqResult-r10 RSRQ-Range OPTIONAL, + ..., + [[ dl-CarrierFreq-v1090 ARFCN-ValueEUTRA-v9e0 OPTIONAL + ]], + [[ rsrqResult-v1250 RSRQ-Range-v1250 OPTIONAL + ]], + [[ rs-sinr-Result-r13 RS-SINR-Range-r13 OPTIONAL + ]] +} + + +maxReestabInfo INTEGER ::= 32 -- Maximum number of KeNB* and shortMAC-I forwarded + -- at handover for re-establishment preparation + + +END + + +NBIOT-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + C-RNTI, + PhysCellId, + SecurityAlgorithmConfig, + ShortMAC-I +FROM EUTRA-RRC-Definitions + + AdditionalReestabInfoList +FROM EUTRA-InterNodeDefinitions + + CarrierFreq-NB-r13, + RadioResourceConfigDedicated-NB-r13, + UE-Capability-NB-r13, + UE-RadioPagingInfo-NB-r13 +FROM NBIOT-RRC-Definitions; + + +HandoverPreparationInformation-NB ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverPreparationInformation-r13 HandoverPreparationInformation-NB-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverPreparationInformation-NB-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo-r13 UE-Capability-NB-r13, + as-Config-r13 AS-Config-NB, + rrm-Config-r13 RRM-Config-NB OPTIONAL, + as-Context-r13 AS-Context-NB OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UEPagingCoverageInformation-NB ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + uePagingCoverageInformation-r13 UEPagingCoverageInformation-NB-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEPagingCoverageInformation-NB-IEs ::= SEQUENCE { +-- the possible value(s) can differ from those sent on Uu + npdcch-NumRepetitionPaging-r13 INTEGER (1..2048) OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UERadioAccessCapabilityInformation-NB ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioAccessCapabilityInformation-r13 + UERadioAccessCapabilityInformation-NB-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioAccessCapabilityInformation-NB-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo-r13 OCTET STRING (CONTAINING UE-Capability-NB-r13), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +UERadioPagingInformation-NB ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioPagingInformation-r13 UERadioPagingInformation-NB-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioPagingInformation-NB-IEs ::= SEQUENCE { + ue-RadioPagingInfo-r13 OCTET STRING (CONTAINING UE-RadioPagingInfo-NB-r13), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +AS-Config-NB ::= SEQUENCE { + sourceRadioResourceConfig-r13 RadioResourceConfigDedicated-NB-r13, + sourceSecurityAlgorithmConfig-r13 SecurityAlgorithmConfig, + sourceUE-Identity-r13 C-RNTI, + sourceDl-CarrierFreq-r13 CarrierFreq-NB-r13, + ... +} + + +AS-Context-NB ::= SEQUENCE { + reestablishmentInfo-r13 ReestablishmentInfo-NB OPTIONAL, + ... +} + + +ReestablishmentInfo-NB ::= SEQUENCE { + sourcePhysCellId-r13 PhysCellId, + targetCellShortMAC-I-r13 ShortMAC-I, + additionalReestabInfoList-r13 AdditionalReestabInfoList OPTIONAL, + ... +} + + + + +RRM-Config-NB ::= SEQUENCE { + ue-InactiveTime ENUMERATED { + s1, s2, s3, s5, s7, s10, s15, s20, + s25, s30, s40, s50, min1, min1s20, min1s40, + min2, min2s30, min3, min3s30, min4, min5, min6, + min7, min8, min9, min10, min12, min14, min17, min20, + min24, min28, min33, min38, min44, min50, hr1, + hr1min30, hr2, hr2min30, hr3, hr3min30, hr4, hr5, hr6, + hr8, hr10, hr13, hr16, hr20, day1, day1hr12, day2, + day2hr12, day3, day4, day5, day7, day10, day14, day19, + day24, day30, dayMoreThan30} OPTIONAL, + ... +} + + +END + + diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h index 47f8a0080adf5311a20c92d9c21312e64dbcd764..0a2043fd4e145eb1f716083936bba7ac44a4cfc1 100644 --- a/openair2/RRC/LITE/defs.h +++ b/openair2/RRC/LITE/defs.h @@ -61,7 +61,7 @@ #include "RRCConnectionReestablishmentRequest.h" #include "BCCH-DL-SCH-Message.h" #include "BCCH-BCH-Message.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MCCH-Message.h" #include "MBSFNAreaConfiguration-r9.h" #include "SCellToAddMod-r10.h" @@ -71,8 +71,59 @@ #include "UE-EUTRA-Capability.h" #include "MeasResults.h" +/* correct Rel(8|10)/Rel14 differences + * the code is in favor of Rel14, those defines do the translation + */ +#if !defined(Rel14) +# define CipheringAlgorithm_r12_t e_SecurityAlgorithmConfig__cipheringAlgorithm +# define CipheringAlgorithm_r12_eea0 SecurityAlgorithmConfig__cipheringAlgorithm_eea0 +# define CipheringAlgorithm_r12_eea1 SecurityAlgorithmConfig__cipheringAlgorithm_eea1 +# define CipheringAlgorithm_r12_eea2 SecurityAlgorithmConfig__cipheringAlgorithm_eea2 +# define CipheringAlgorithm_r12_spare1 SecurityAlgorithmConfig__cipheringAlgorithm_spare1 +# define Alpha_r12_al0 UplinkPowerControlCommon__alpha_al0 +# define Alpha_r12_al04 UplinkPowerControlCommon__alpha_al04 +# define Alpha_r12_al05 UplinkPowerControlCommon__alpha_al05 +# define Alpha_r12_al06 UplinkPowerControlCommon__alpha_al06 +# define Alpha_r12_al07 UplinkPowerControlCommon__alpha_al07 +# define Alpha_r12_al08 UplinkPowerControlCommon__alpha_al08 +# define Alpha_r12_al09 UplinkPowerControlCommon__alpha_al09 +# define Alpha_r12_al1 UplinkPowerControlCommon__alpha_al1 +# define PreambleTransMax_n3 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n3 +# define PreambleTransMax_n4 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n4 +# define PreambleTransMax_n5 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n5 +# define PreambleTransMax_n6 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n6 +# define PreambleTransMax_n7 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n7 +# define PreambleTransMax_n8 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n8 +# define PreambleTransMax_n10 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n10 +# define PreambleTransMax_n20 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n20 +# define PreambleTransMax_n50 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n50 +# define PreambleTransMax_n100 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n100 +# define PreambleTransMax_n200 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n200 +# define PeriodicBSR_Timer_r12_sf5 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf5 +# define PeriodicBSR_Timer_r12_sf10 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf10 +# define PeriodicBSR_Timer_r12_sf16 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf16 +# define PeriodicBSR_Timer_r12_sf20 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf20 +# define PeriodicBSR_Timer_r12_sf32 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf32 +# define PeriodicBSR_Timer_r12_sf40 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf40 +# define PeriodicBSR_Timer_r12_sf64 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf64 +# define PeriodicBSR_Timer_r12_sf80 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf80 +# define PeriodicBSR_Timer_r12_sf128 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf128 +# define PeriodicBSR_Timer_r12_sf160 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf160 +# define PeriodicBSR_Timer_r12_sf320 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf320 +# define PeriodicBSR_Timer_r12_sf640 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf640 +# define PeriodicBSR_Timer_r12_sf1280 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf1280 +# define PeriodicBSR_Timer_r12_sf2560 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf2560 +# define PeriodicBSR_Timer_r12_infinity MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity +# define RetxBSR_Timer_r12_sf320 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf320 +# define RetxBSR_Timer_r12_sf640 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf640 +# define RetxBSR_Timer_r12_sf1280 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf1280 +# define RetxBSR_Timer_r12_sf2560 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560 +# define RetxBSR_Timer_r12_sf5120 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf5120 +# define RetxBSR_Timer_r12_sf10240 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240 +#endif + // This corrects something generated by asn1c which is different between Rel8 and Rel10 -#ifndef Rel10 +#if !defined(Rel10) && !defined(Rel14) #define SystemInformation_r8_IEs__sib_TypeAndInfo__Member SystemInformation_r8_IEs_sib_TypeAndInfo_Member #define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib2 #define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib3 @@ -86,7 +137,7 @@ #define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib11 #endif /* -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib12_v920 #define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib13_v920 #endif @@ -194,7 +245,7 @@ typedef struct UE_RRC_INFO_s { uint8_t SIB1systemInfoValueTag; uint32_t SIStatus; uint32_t SIcnt; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) uint8_t MCCHStatus[8]; // MAX_MBSFN_AREA #endif uint8_t SIwindowsize; //!< Corresponds to the SIB1 si-WindowLength parameter. The unit is ms. Possible values are (final): 1,2,5,10,15,20,40 @@ -301,7 +352,7 @@ typedef struct HANDOVER_INFO_UE_s { typedef struct eNB_RRC_UE_s { uint8_t primaryCC_id; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) SCellToAddMod_r10_t sCell_config[2]; #endif SRB_ToAddModList_t* SRB_configList; @@ -329,7 +380,7 @@ typedef struct eNB_RRC_UE_s { uint8_t kenb[32]; #endif /* Used integrity/ciphering algorithms */ - e_SecurityAlgorithmConfig__cipheringAlgorithm ciphering_algorithm; + CipheringAlgorithm_r12_t ciphering_algorithm; e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm; uint8_t Status; @@ -400,7 +451,7 @@ typedef struct { SystemInformationBlockType1_t *sib1; SystemInformationBlockType2_t *sib2; SystemInformationBlockType3_t *sib3; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) SystemInformationBlockType13_r9_t *sib13; uint8_t MBMS_flag; uint8_t num_mbsfn_sync_area; @@ -489,7 +540,7 @@ typedef struct UE_RRC_INST_s { SystemInformationBlockType10_t *sib10[NB_CNX_UE]; SystemInformationBlockType11_t *sib11[NB_CNX_UE]; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) uint8_t MBMS_flag; uint8_t *MCCH_MESSAGE[NB_CNX_UE]; uint8_t sizeof_MCCH_MESSAGE[NB_CNX_UE]; @@ -535,7 +586,7 @@ typedef struct UE_RRC_INST_s { #endif /* Used integrity/ciphering algorithms */ - e_SecurityAlgorithmConfig__cipheringAlgorithm ciphering_algorithm; + CipheringAlgorithm_r12_t ciphering_algorithm; e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm; } UE_RRC_INST; diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c index 8a8aaf73ba06e5b1f27a86db094d89531b8c8440..6798212fb2e5f4082f7ea92a0a68d841e0dc7935 100644 --- a/openair2/RRC/LITE/rrc_UE.c +++ b/openair2/RRC/LITE/rrc_UE.c @@ -53,7 +53,7 @@ #include "DL-DCCH-Message.h" #include "BCCH-DL-SCH-Message.h" #include "PCCH-Message.h" -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) #include "MCCH-Message.h" #endif #include "MeasConfig.h" @@ -145,7 +145,7 @@ static uint8_t check_trigger_meas_event( Q_OffsetRange_t ofn, Q_OffsetRange_t ocn, Hysteresis_t hys, Q_OffsetRange_t ofs, Q_OffsetRange_t ocs, long a3_offset, TimeToTrigger_t ttt); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) static void decode_MBSFNAreaConfiguration(module_id_t module_idP, uint8_t eNB_index, frame_t frameP,uint8_t mbsfn_sync_area); #endif @@ -256,7 +256,7 @@ static void init_SI_UE( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_ UE_rrc_inst[ctxt_pP->module_id].sib9[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType9_t) ); UE_rrc_inst[ctxt_pP->module_id].sib10[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType10_t) ); UE_rrc_inst[ctxt_pP->module_id].sib11[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType11_t) ); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) UE_rrc_inst[ctxt_pP->module_id].sib12[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType12_r9_t) ); UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType13_r9_t) ); #endif @@ -268,7 +268,7 @@ static void init_SI_UE( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_ UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt = 0; } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) //----------------------------------------------------------------------------- #if 0 static void init_MCCH_UE(module_id_t ue_mod_idP, uint8_t eNB_index) @@ -328,8 +328,8 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_ UE_rrc_inst[ctxt.module_id].Srb1[eNB_index].Active=0; UE_rrc_inst[ctxt.module_id].Srb2[eNB_index].Active=0; UE_rrc_inst[ctxt.module_id].HandoverInfoUe.measFlag=1; - UE_rrc_inst[ctxt.module_id].ciphering_algorithm = SecurityAlgorithmConfig__cipheringAlgorithm_eea0; -#ifdef Rel10 + UE_rrc_inst[ctxt.module_id].ciphering_algorithm = CipheringAlgorithm_r12_eea0; +#if defined(Rel10) || defined(Rel14) UE_rrc_inst[ctxt.module_id].integrity_algorithm = SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920; #else UE_rrc_inst[ctxt.module_id].integrity_algorithm = SecurityAlgorithmConfig__integrityProtAlgorithm_reserved; @@ -404,6 +404,7 @@ void rrc_ue_generate_RRCConnectionRequest( const protocol_ctxt_t* const ctxt_pP, mui_t rrc_mui=0; +#if !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)) /* NAS Attach request with IMSI */ static const char const nas_attach_req_imsi[] = { 0x07, 0x41, @@ -417,7 +418,9 @@ static const char const nas_attach_req_imsi[] = { 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; +#endif /* !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)) */ +#if 0 /* NAS Attach request with GUTI */ static const char const nas_attach_req_guti[] = { 0x07, 0x41, @@ -431,6 +434,7 @@ static const char const nas_attach_req_guti[] = { 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; +#endif //----------------------------------------------------------------------------- static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ) @@ -743,10 +747,10 @@ rrc_ue_establish_drb( # ifdef OAI_EMU oai_emulation.info.oai_ifup[ue_mod_idP]=1; # endif - LOG_I(OIP,"[UE %d] Config the oai%d to send/receive pkt on DRB %d to/from the protocol stack\n", + LOG_I(OIP,"[UE %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n", ue_mod_idP, ip_addr_offset3+ue_mod_idP, - (eNB_index * maxDRB) + DRB_config->drb_Identity); + (long int)((eNB_index * maxDRB) + DRB_config->drb_Identity)); rb_conf_ipv4(0,//add ue_mod_idP,//cx align with the UE index @@ -821,7 +825,7 @@ rrc_ue_process_measConfig( rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif @@ -838,7 +842,7 @@ rrc_ue_process_measConfig( NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *)NULL, @@ -975,6 +979,8 @@ rrc_ue_update_radioResourceConfigDedicated(RadioResourceConfigDedicated_t* radio physicalConfigDedicated2->pusch_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->pusch_ConfigDedicated)); physicalConfigDedicated2->pucch_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->pucch_ConfigDedicated)); physicalConfigDedicated2->cqi_ReportConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig)); + physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic + = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic)); physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated)); physicalConfigDedicated2->schedulingRequestConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->schedulingRequestConfig)); physicalConfigDedicated2->antennaInfo = CALLOC(1,sizeof(*physicalConfigDedicated2->antennaInfo)); @@ -1036,14 +1042,25 @@ rrc_ue_update_radioResourceConfigDedicated(RadioResourceConfigDedicated_t* radio // Update cqi_ReportConfig if(radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig != NULL) { - LOG_I(RRC,"Update cqi_ReportConfig config \n"); + LOG_I(RRC,"Update cqi_ReportConfig config (size=%zu,%zu)\n", sizeof(*physicalConfigDedicated2->cqi_ReportConfig), sizeof(CQI_ReportConfig_t)); if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig == NULL) UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig = CALLOC(1,sizeof(CQI_ReportConfig_t)); memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig, (char*)radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig, - sizeof(physicalConfigDedicated2->cqi_ReportConfig)); + sizeof(*physicalConfigDedicated2->cqi_ReportConfig)); + + if (radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic != NULL) { + LOG_I(RRC,"Update cqi_ReportPeriodic config (size=%zu,%zu)\n", sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic), sizeof(CQI_ReportPeriodic_t)); + + if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig->cqi_ReportPeriodic == NULL) + UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig->cqi_ReportPeriodic = CALLOC(1,sizeof(CQI_ReportPeriodic_t)); + + memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig->cqi_ReportPeriodic, + (char*)radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic, + sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic)); + } } else { @@ -1095,6 +1112,17 @@ rrc_ue_update_radioResourceConfigDedicated(RadioResourceConfigDedicated_t* radio memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo, (char*)radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo, sizeof(physicalConfigDedicated2->antennaInfo)); + + UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.transmissionMode = + radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode; + UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.codebookSubsetRestriction = + radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.codebookSubsetRestriction; + UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection = + radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection; + + LOG_I(PHY,"New Transmission Mode %ld \n",radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode); + LOG_I(PHY,"Configured Transmission Mode %ld \n",UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.transmissionMode); + } else { @@ -1259,7 +1287,7 @@ rrc_ue_process_radioResourceConfigDedicated( kRRCenc, kRRCint, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,(PMCH_InfoList_r9_t *)NULL #endif ,NULL); @@ -1269,7 +1297,7 @@ rrc_ue_process_radioResourceConfigDedicated( radioResourceConfigDedicated->srb_ToAddModList, (DRB_ToAddModList_t*)NULL, (DRB_ToReleaseList_t*)NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,(PMCH_InfoList_r9_t *)NULL #endif ); @@ -1308,7 +1336,7 @@ rrc_ue_process_radioResourceConfigDedicated( rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index], -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif @@ -1325,7 +1353,7 @@ rrc_ue_process_radioResourceConfigDedicated( NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *)NULL, @@ -1366,7 +1394,7 @@ rrc_ue_process_radioResourceConfigDedicated( rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index], -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif @@ -1383,7 +1411,7 @@ rrc_ue_process_radioResourceConfigDedicated( NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *)NULL, @@ -1439,7 +1467,7 @@ rrc_ue_process_radioResourceConfigDedicated( NULL, NULL, kUPenc -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,(PMCH_InfoList_r9_t *)NULL #endif , UE_rrc_inst[ctxt_pP->module_id].defaultDRB); @@ -1449,7 +1477,7 @@ rrc_ue_process_radioResourceConfigDedicated( (SRB_ToAddModList_t*)NULL, radioResourceConfigDedicated->drb_ToAddModList, (DRB_ToReleaseList_t*)NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,(PMCH_InfoList_r9_t *)NULL #endif ); @@ -1473,7 +1501,7 @@ rrc_ue_process_radioResourceConfigDedicated( rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index], -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10, #endif @@ -1490,7 +1518,7 @@ rrc_ue_process_radioResourceConfigDedicated( NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *)NULL, @@ -1544,26 +1572,26 @@ rrc_ue_process_securityModeCommand( ctxt_pP->module_id,ctxt_pP->frame,eNB_index); switch (securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm) { - case SecurityAlgorithmConfig__cipheringAlgorithm_eea0: + case CipheringAlgorithm_r12_eea0: LOG_I(RRC,"[UE %d] Security algorithm is set to eea0\n", ctxt_pP->module_id); - securityMode= SecurityAlgorithmConfig__cipheringAlgorithm_eea0; + securityMode= CipheringAlgorithm_r12_eea0; break; - case SecurityAlgorithmConfig__cipheringAlgorithm_eea1: + case CipheringAlgorithm_r12_eea1: LOG_I(RRC,"[UE %d] Security algorithm is set to eea1\n",ctxt_pP->module_id); - securityMode= SecurityAlgorithmConfig__cipheringAlgorithm_eea1; + securityMode= CipheringAlgorithm_r12_eea1; break; - case SecurityAlgorithmConfig__cipheringAlgorithm_eea2: + case CipheringAlgorithm_r12_eea2: LOG_I(RRC,"[UE %d] Security algorithm is set to eea2\n", ctxt_pP->module_id); - securityMode = SecurityAlgorithmConfig__cipheringAlgorithm_eea2; + securityMode = CipheringAlgorithm_r12_eea2; break; default: LOG_I(RRC,"[UE %d] Security algorithm is set to none\n",ctxt_pP->module_id); - securityMode = SecurityAlgorithmConfig__cipheringAlgorithm_spare1; + securityMode = CipheringAlgorithm_r12_spare1; break; } @@ -1989,18 +2017,18 @@ rrc_ue_process_mobilityControlInfo( NULL, // key rrc encryption NULL, // key rrc integrity NULL // key encryption - #ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,NULL - #endif +#endif ,NULL); rrc_rlc_config_asn1_req(NB_eNB_INST+ue_mod_idP, frameP,0,eNB_index, NULL,// SRB_ToAddModList NULL,// DRB_ToAddModList drb2release_list // DRB_ToReleaseList - #ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,NULL - #endif +#endif ,NULL); */ @@ -2035,7 +2063,7 @@ rrc_ue_process_mobilityControlInfo( eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -2052,7 +2080,7 @@ rrc_ue_process_mobilityControlInfo( NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,0, (MBSFN_AreaInfoList_r9_t *)NULL, (PMCH_InfoList_r9_t *)NULL @@ -2405,7 +2433,7 @@ rrc_ue_decode_dcch( case DL_DCCH_MessageType__c1_PR_counterCheck: break; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) case DL_DCCH_MessageType__c1_PR_ueInformationRequest_r9: break; @@ -2420,7 +2448,9 @@ rrc_ue_decode_dcch( case DL_DCCH_MessageType__c1_PR_spare1: case DL_DCCH_MessageType__c1_PR_spare2: case DL_DCCH_MessageType__c1_PR_spare3: +#if !defined(Rel14) case DL_DCCH_MessageType__c1_PR_spare4: +#endif break; default: @@ -2889,7 +2919,7 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_ rrc_mac_config_req(ctxt_pP->module_id, 0, ENB_FLAG_NO, 0, eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -2906,7 +2936,7 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_ NULL, NULL, (MBSFN_SubframeConfigList_t *)NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,0, (MBSFN_AreaInfoList_r9_t *)NULL, (PMCH_InfoList_r9_t *)NULL @@ -3131,13 +3161,13 @@ static void dump_sib2( SystemInformationBlockType2_t *sib2 ) sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig ); LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission : %d\n", sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission ); -#if 0 - /* TODO: test this - commented for the moment */ - if (sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts : %ld\n", - /* TODO: check that it's okay to access [0] */ - sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts[0] ); -#endif + + if(sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) + { + LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts : %ld\n", + /* TODO: check that it's okay to access [0] */ + sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts[0] ); + } } // uplinkPowerControlCommon @@ -3163,7 +3193,7 @@ static void dump_sib2( SystemInformationBlockType2_t *sib2 ) LOG_I( RRC, "radioResourceConfigCommon.ul_CyclicPrefixLength : %ld\n", sib2->radioResourceConfigCommon.ul_CyclicPrefixLength ); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // UplinkPowerControlCommon_v1020 // ... #endif @@ -3195,7 +3225,7 @@ static void dump_sib2( SystemInformationBlockType2_t *sib2 ) LOG_I( RRC, "timeAlignmentTimerCommon : %ld\n", sib2->timeAlignmentTimerCommon ); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (sib2->lateNonCriticalExtension) { LOG_I( RRC, "lateNonCriticalExtension : %p\n", sib2->lateNonCriticalExtension ); @@ -3464,7 +3494,7 @@ static void dump_sib5( SystemInformationBlockType5_t *sib5 ) } } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (ifcfInfo->ext1 && ifcfInfo->ext1->q_QualMin_r9) LOG_I(RRC," Q_QualMin_r9 : %ld\n",*ifcfInfo->ext1->q_QualMin_r9); @@ -3477,7 +3507,7 @@ static void dump_sib5( SystemInformationBlockType5_t *sib5 ) } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) static void dump_sib13( SystemInformationBlockType13_r9_t *sib13 ) { LOG_I( RRC, "[UE] Dumping SIB13\n" ); @@ -3525,7 +3555,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in rrc_mac_config_req(ctxt_pP->module_id, 0, ENB_FLAG_NO, 0, eNB_index, &UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->radioResourceConfigCommon, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, #endif (MeasObjectToAddMod_t **)NULL, @@ -3541,7 +3571,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.ul_Bandwidth, &UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.additionalSpectrumEmission, UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->mbsfn_SubframeConfigList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,0, (MBSFN_AreaInfoList_r9_t *)NULL, (PMCH_InfoList_r9_t *)NULL @@ -3552,7 +3582,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in #endif ); // After SI is received, prepare RRCConnectionRequest -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (UE_rrc_inst[ctxt_pP->module_id].MBMS_flag < 3) // see -Q option #endif @@ -3683,7 +3713,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in } break; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920: if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&2048) == 0) { @@ -4092,7 +4122,7 @@ static uint8_t check_trigger_meas_event( return 0; } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) //----------------------------------------------------------------------------- int decode_MCCH_Message( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t* const Sdu, const uint8_t Sdu_len, const uint8_t mbsfn_sync_area ) { @@ -4166,7 +4196,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i rrc_mac_config_req(ue_mod_idP,0,ENB_FLAG_NO,0,eNB_index, (RadioResourceConfigCommonSIB_t *)NULL, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -4183,7 +4213,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i NULL, NULL, (MBSFN_SubframeConfigList_t *)NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *)NULL, @@ -4209,7 +4239,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i NULL, // key rrc encryption NULL, // key rrc integrity NULL // key encryption -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ,&(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9) #endif ,NULL); @@ -4218,7 +4248,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i NULL,// SRB_ToAddModList NULL,// DRB_ToAddModList NULL,// DRB_ToReleaseList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) &(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9) #endif ); @@ -4325,7 +4355,7 @@ void *rrc_ue_task( void *args_p ) RRC_MAC_CCCH_DATA_IND (msg_p).enb_index); break; -# ifdef Rel10 +# if defined(Rel10) || defined(Rel14) case RRC_MAC_MCCH_DATA_IND: LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d, mbsfn SA %d\n", ue_mod_id, msg_name, @@ -4395,7 +4425,6 @@ void *rrc_ue_task( void *args_p ) /* NAS messages */ case NAS_CELL_SELECTION_REQ: - ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */ LOG_D(RRC, "[UE %d] Received %s: state %d, plmnID (%d%d%d.%d%d%d), rat %x\n", ue_mod_id, msg_name, rrc_get_state(ue_mod_id), NAS_CELL_SELECTION_REQ (msg_p).plmnID.MCCdigit1, @@ -4696,7 +4725,6 @@ void *rrc_ue_task( void *args_p ) break; case RRC_RAL_CONNECTION_RELEASE_REQ: - ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */ LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, msg_name); break; #endif diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index b039ecd8de2c20f91d47ea4490bb107362bfb24a..3f7fa3067c946d5dbba02bcaced61cf227e7c4e3 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -265,7 +265,7 @@ openair_rrc_top_init( UE_rrc_inst[module_id].UECapability_size = UECap->sdu_size; } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) LOG_I(RRC,"[UE] eMBMS active state is %d \n", eMBMS_active); for (module_id=0; module_id<NB_UE_INST; module_id++) { @@ -286,7 +286,7 @@ openair_rrc_top_init( eNB_rrc_inst[module_id].HO_flag = (uint8_t)HO_active; } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) LOG_I(RRC,"[eNB] eMBMS active state is %d \n", eMBMS_active); for (module_id=0; module_id<NB_eNB_INST; module_id++) { diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 8b5b012ff1a7178a2a8dcf9a49ea1211abd09020..659f1c57b0e3f6595bdb1b8c52386c509d1ea563 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -57,7 +57,7 @@ #include "T.h" -//#ifdef Rel10 +//#if defined(Rel10) || defined(Rel14) #include "MeasResults.h" //#endif @@ -125,7 +125,7 @@ init_SI( { uint8_t SIwindowsize = 1; uint16_t SIperiod = 8; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) int i; #endif /* @@ -223,7 +223,7 @@ init_SI( &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].systemInformation, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib3 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib13, eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].MBMS_flag #endif @@ -281,7 +281,7 @@ init_SI( eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->radioResourceConfigCommon.pusch_ConfigCommon. ul_ReferenceSignalsPUSCH.cyclicShift); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) if (eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].MBMS_flag > 0) { for (i = 0; i < eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->mbsfn_SubframeConfigList->list.count; i++) { @@ -326,7 +326,7 @@ init_SI( (RadioResourceConfigCommonSIB_t *) & eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->radioResourceConfigCommon, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -341,7 +341,7 @@ init_SI( eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->freqInfo.ul_Bandwidth, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->freqInfo.additionalSpectrumEmission, (MBSFN_SubframeConfigList_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->mbsfn_SubframeConfigList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].MBMS_flag, (MBSFN_AreaInfoList_r9_t*) & eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib13->mbsfn_AreaInfoList_r9, @@ -359,7 +359,7 @@ init_SI( } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) /*------------------------------------------------------------------------------*/ static void init_MCCH( @@ -422,7 +422,7 @@ init_MCCH( rrc_mac_config_req(enb_mod_idP, CC_id, ENB_FLAG_YES, 0, 0, (RadioResourceConfigCommonSIB_t *) NULL, (struct PhysicalConfigDedicated *)NULL, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -433,7 +433,7 @@ init_MCCH( (MeasGapConfig_t *) NULL, (TDD_Config_t *) NULL, NULL, (uint8_t *) NULL, (uint16_t *) NULL, NULL, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL -# ifdef Rel10 +# if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *) NULL, @@ -473,7 +473,7 @@ static void init_MBMS( NULL, // key rrc encryption NULL, // key rrc integrity NULL // key encryption -# ifdef Rel10 +# if defined(Rel10) || defined(Rel14) , &(eNB_rrc_inst[enb_mod_idP].carrier[CC_id].mcch_message->pmch_InfoList_r9) # endif ,NULL); @@ -693,7 +693,7 @@ rrc_eNB_free_mem_UE_context( PROTOCOL_RRC_CTXT_UE_FMT" Clearing UE context 0x%p (free internal structs)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_pP); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_SCellToAddMod_r10, &ue_context_pP->ue_context.sCell_config[0]); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_SCellToAddMod_r10, &ue_context_pP->ue_context.sCell_config[1]); #endif @@ -1369,7 +1369,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , (SCellToAddMod_r10_t*)NULL #endif ); @@ -1469,7 +1469,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; MeasIdToAddModList_t *MeasId_list = NULL; MeasIdToAddMod_t *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; -#if Rel10 +#if defined(Rel10) || defined(Rel14) long *sr_ProhibitTimer_r9 = NULL; // uint8_t sCellIndexToAdd = rrc_find_free_SCell_index(enb_mod_idP, ue_mod_idP, 1); //uint8_t sCellIndexToAdd = 0; @@ -1671,9 +1671,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons *maxHARQ_Tx = MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; periodicBSR_Timer = CALLOC(1, sizeof(long)); - *periodicBSR_Timer = MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf64; + *periodicBSR_Timer = PeriodicBSR_Timer_r12_sf64; mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; - mac_MainConfig->ul_SCH_Config->retxBSR_Timer = MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf320; + mac_MainConfig->ul_SCH_Config->retxBSR_Timer = RetxBSR_Timer_r12_sf320; mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE mac_MainConfig->timeAlignmentTimerDedicated = TimeAlignmentTimer_infinity; @@ -1689,7 +1689,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; // Value dB1 =1 dB, dB3 = 3 dB -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long)); *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2= 2*SR mac_MainConfig->ext1 = CALLOC(1, sizeof(struct MAC_MainConfig__ext1)); @@ -1756,7 +1756,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons //feedback mode needs to be set as well //TODO: I think this is taken into account in the PHY automatically based on the transmission mode variable printf("setting cqi reporting mode to rm31\n"); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=CQI_ReportModeAperiodic_rm31; #else *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=CQI_ReportConfig__cqi_ReportModeAperiodic_rm31; // HLC CQI, no PMI @@ -2102,7 +2102,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons (RSRP_Range_t*)rsrp, (C_RNTI_t*)cba_RNTI, (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , (SCellToAddMod_r10_t*)NULL #endif ); @@ -2173,7 +2173,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_SCell( uint8_t size; uint8_t buffer[100]; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) uint8_t sCellIndexToAdd = 0; //one SCell so far // uint8_t sCellIndexToAdd; @@ -2207,7 +2207,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_SCell( (C_RNTI_t*)NULL, (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , ue_context_pP->ue_context.sCell_config #endif ); @@ -2264,12 +2264,12 @@ rrc_eNB_process_MeasurementReport( measResult.rsrqResult)); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) LOG_I(RRC, "RSRP of Source %ld\n", measResults2->measResultPCell.rsrpResult); LOG_I(RRC, "RSRQ of Source %ld\n", measResults2->measResultPCell.rsrqResult); #else - LOG_I(RRC, "RSRP of Source %d\n", measResults2->measResultServCell.rsrpResult); - LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult); + LOG_I(RRC, "RSRP of Source %ld\n", measResults2->measResultServCell.rsrpResult); + LOG_I(RRC, "RSRQ of Source %ld\n", measResults2->measResultServCell.rsrqResult); #endif if (ue_context_pP->ue_context.handover_info->ho_prepare != 0xF0) { @@ -2531,7 +2531,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( // HandoverCommand_t handoverCommand; //uint8_t sourceModId = // get_adjacent_cell_mod_id(ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->sourcePhysCellId); -#if Rel10 +#if defined(Rel10) || defined(Rel14) long *sr_ProhibitTimer_r9; #endif @@ -2779,7 +2779,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( 0, (RadioResourceConfigCommonSIB_t*) NULL, ue_context_pP->ue_context.physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -2796,7 +2796,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL #endif #ifdef CBA @@ -2899,10 +2899,10 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; periodicBSR_Timer = CALLOC(1, sizeof(long)); - *periodicBSR_Timer = MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf64; + *periodicBSR_Timer = PeriodicBSR_Timer_r12_sf64; mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; - mac_MainConfig->ul_SCH_Config->retxBSR_Timer = MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf320; + mac_MainConfig->ul_SCH_Config->retxBSR_Timer = RetxBSR_Timer_r12_sf320; mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE @@ -2917,7 +2917,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; // Value dB1 =1 dB, dB3 = 3 dB -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long)); *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2= 2*SR mac_MainConfig->ext1 = CALLOC(1, sizeof(struct MAC_MainConfig__ext1)); @@ -3279,7 +3279,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( rrc_pdcp_config_asn1_req(&ctxt, ue_context_pP->ue_context.SRB_configList, (DRB_ToAddModList_t *) NULL, (DRB_ToReleaseList_t *) NULL, 0xff, NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL #endif ,NULL); @@ -3287,7 +3287,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( rrc_rlc_config_asn1_req(&ctxt, ue_context_pP->ue_context.SRB_configList, (DRB_ToAddModList_t *) NULL, (DRB_ToReleaseList_t *) NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL #endif ); @@ -3318,7 +3318,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( NULL, NULL, dedicatedInfoNASList -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , NULL // SCellToAddMod_r10_t #endif ); @@ -3353,7 +3353,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( 0, (RadioResourceConfigCommonSIB_t *) NULL, ue_context_pP->ue_context.physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -3365,7 +3365,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( (TDD_Config_t *) NULL, (MobilityControlInfo_t *) mobilityInfo, (uint8_t *) NULL, (uint16_t *) NULL, NULL, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL #endif #ifdef CBA @@ -3432,7 +3432,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( ) //----------------------------------------------------------------------------- { - int i; + int i, drb_id; #ifdef PDCP_USE_NETLINK int oip_ifup = 0; int dest_ip_offset = 0; @@ -3521,7 +3521,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( kRRCenc, kRRCint, kUPenc -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL #endif ,NULL); @@ -3531,7 +3531,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( SRB_configList, // NULL, //LG-RK 14/05/2014 SRB_configList, DRB_configList, (DRB_ToReleaseList_t *) NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL #endif ); @@ -3564,6 +3564,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( if (DRB_configList != NULL) { for (i = 0; i < DRB_configList->list.count; i++) { // num max DRB (11-3-8) if (DRB_configList->list.array[i]) { + drb_id = (int)DRB_configList->list.array[i]->drb_Identity; LOG_I(RRC, "[eNB %d] Frame %d : Logical Channel UL-DCCH, Received RRCConnectionReconfigurationComplete from UE rnti %x, reconfiguring DRB %d/LCID %d\n", ctxt_pP->module_id, @@ -3580,7 +3581,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (int)DRB_configList->list.array[i]->drb_Identity, (int)*DRB_configList->list.array[i]->logicalChannelIdentity); - if (ue_context_pP->ue_context.DRB_active[i] == 0) { + if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) { /* rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_ADD, (ue_mod_idP * NB_RB_MAX) + *DRB_configList->list.array[i]->logicalChannelIdentity,UNDEF_SECURITY_MODE); @@ -3588,7 +3589,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (ue_mod_idP * NB_RB_MAX) + (int)*eNB_rrc_inst[ctxt_pP->module_id].DRB_config[ue_mod_idP][i]->logicalChannelIdentity, RADIO_ACCESS_BEARER,Rlc_info_um); */ - ue_context_pP->ue_context.DRB_active[i] = 1; + ue_context_pP->ue_context.DRB_active[drb_id] = 1; LOG_D(RRC, "[eNB %d] Frame %d: Establish RLC UM Bidirectional, DRB %d Active\n", @@ -3612,9 +3613,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( dest_ip_offset = 8; # endif LOG_I(OIP, - "[eNB %d] Config the oai%d to send/receive pkt on DRB %d to/from the protocol stack\n", + "[eNB %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n", ctxt_pP->module_id, ctxt_pP->module_id, - (ue_context_pP->local_uid * maxDRB) + DRB_configList->list.array[i]->drb_Identity); + (long int)((ue_context_pP->local_uid * maxDRB) + DRB_configList->list.array[i]->drb_Identity)); ue_module_id = oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid]; rb_conf_ipv4(0, //add ue_module_id, //cx @@ -3650,7 +3651,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( 0, (RadioResourceConfigCommonSIB_t *) NULL, ue_context_pP->ue_context.physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -3663,7 +3664,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( NULL, (uint8_t *) NULL, (uint16_t *) NULL, NULL, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL #endif #ifdef CBA @@ -3673,7 +3674,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( } else { // remove LCHAN from MAC/PHY - if (ue_context_pP->ue_context.DRB_active[i] == 1) { + if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { // DRB has just been removed so remove RLC + PDCP for DRB /* rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_REMOVE, (ue_mod_idP * NB_RB_MAX) + DRB2LCHAN[i],UNDEF_SECURITY_MODE); @@ -3687,7 +3688,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( Rlc_info_um); } - ue_context_pP->ue_context.DRB_active[i] = 0; + ue_context_pP->ue_context.DRB_active[drb_id] = 0; LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (DRB) ---> MAC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); @@ -3698,7 +3699,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( 0, (RadioResourceConfigCommonSIB_t *) NULL, ue_context_pP->ue_context.physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -3709,7 +3710,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (MeasGapConfig_t *) NULL, (TDD_Config_t *) NULL, NULL, (uint8_t *) NULL, (uint16_t *) NULL, NULL, NULL, NULL, NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL #endif #ifdef CBA @@ -3793,7 +3794,7 @@ rrc_eNB_generate_RRCConnectionSetup( 0, (RadioResourceConfigCommonSIB_t *) NULL, ue_context_pP->ue_context.physicalConfigDedicated, -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) (SCellToAddMod_r10_t *)NULL, //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, #endif @@ -3806,7 +3807,7 @@ rrc_eNB_generate_RRCConnectionSetup( NULL, (uint8_t *) NULL, (uint16_t *) NULL, NULL, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL #endif #ifdef CBA @@ -3922,11 +3923,15 @@ while ( eNB_rrc_inst == NULL ) { LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Checking release \n", PROTOCOL_RRC_CTXT_ARGS(&ctxt)); -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) // This has to come from some top-level configuration // only CC_id 0 is logged +#if defined(Rel10) LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Rel10 RRC detected, MBMS flag %d\n", +#else + LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Rel14 RRC detected, MBMS flag %d\n", +#endif PROTOCOL_RRC_CTXT_ARGS(&ctxt), eNB_rrc_inst[ctxt.module_id].carrier[0].MBMS_flag); @@ -3965,7 +3970,7 @@ while ( eNB_rrc_inst == NULL ) { ); } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { switch (eNB_rrc_inst[ctxt.module_id].carrier[CC_id].MBMS_flag) { @@ -4348,7 +4353,7 @@ rrc_eNB_decode_ccch( NULL, NULL, NULL -# ifdef Rel10 +# if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL # endif ,NULL); @@ -4357,7 +4362,7 @@ rrc_eNB_decode_ccch( ue_context_p->ue_context.SRB_configList, (DRB_ToAddModList_t*) NULL, (DRB_ToReleaseList_t*) NULL -# ifdef Rel10 +# if defined(Rel10) || defined(Rel14) , (PMCH_InfoList_r9_t *) NULL # endif ); @@ -4870,7 +4875,7 @@ rrc_eNB_decode_dcch( break; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) case UL_DCCH_MessageType__c1_PR_ueInformationResponse_r9: T(T_ENB_RRC_UE_INFORMATION_RESPONSE_R9, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index 8984eb933c60c1e959e9cad9b5bd5c9c9b90c390..f3c22abeff3b432010cdfa5a35c4ac973ec9b221 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -69,7 +69,7 @@ static const uint16_t S1AP_ENCRYPTION_EEA2_MASK = 0x4000; static const uint16_t S1AP_INTEGRITY_EIA1_MASK = 0x8000; static const uint16_t S1AP_INTEGRITY_EIA2_MASK = 0x4000; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) # define INTEGRITY_ALGORITHM_NONE SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920 #else #ifdef EXMIMO_IOT @@ -228,21 +228,21 @@ rrc_eNB_get_ue_context_from_s1ap_ids( *\param algorithms The bit mask of available algorithms received from S1AP. *\return the selected algorithm. */ -static e_SecurityAlgorithmConfig__cipheringAlgorithm rrc_eNB_select_ciphering(uint16_t algorithms) +static CipheringAlgorithm_r12_t rrc_eNB_select_ciphering(uint16_t algorithms) { //#warning "Forced return SecurityAlgorithmConfig__cipheringAlgorithm_eea0, to be deleted in future" - return SecurityAlgorithmConfig__cipheringAlgorithm_eea0; + return CipheringAlgorithm_r12_eea0; if (algorithms & S1AP_ENCRYPTION_EEA2_MASK) { - return SecurityAlgorithmConfig__cipheringAlgorithm_eea2; + return CipheringAlgorithm_r12_eea2; } if (algorithms & S1AP_ENCRYPTION_EEA1_MASK) { - return SecurityAlgorithmConfig__cipheringAlgorithm_eea1; + return CipheringAlgorithm_r12_eea1; } - return SecurityAlgorithmConfig__cipheringAlgorithm_eea0; + return CipheringAlgorithm_r12_eea0; } /*! \fn e_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_integrity(uint16_t algorithms) @@ -279,7 +279,7 @@ rrc_eNB_process_security( ) { boolean_t changed = FALSE; - e_SecurityAlgorithmConfig__cipheringAlgorithm cipheringAlgorithm; + CipheringAlgorithm_r12_t cipheringAlgorithm; e_SecurityAlgorithmConfig__integrityProtAlgorithm integrityProtAlgorithm; /* Save security parameters */ @@ -287,10 +287,10 @@ rrc_eNB_process_security( // translation LOG_D(RRC, - "[eNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %u NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n", + "[eNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %lu NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n", ctxt_pP->module_id, ue_context_pP->ue_context.security_capabilities.encryption_algorithms, - ue_context_pP->ue_context.ciphering_algorithm, + (unsigned long)ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.security_capabilities.integrity_algorithms, ue_context_pP->ue_context.integrity_algorithm); /* Select relevant algorithms */ @@ -308,11 +308,11 @@ rrc_eNB_process_security( changed = TRUE; } - LOG_I (RRC, "[eNB %d][UE %x] Selected security algorithms (%p): %x, %x, %s\n", + LOG_I (RRC, "[eNB %d][UE %x] Selected security algorithms (%p): %lx, %x, %s\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti, security_capabilities_pP, - cipheringAlgorithm, + (unsigned long)cipheringAlgorithm, integrityProtAlgorithm, changed ? "changed" : "same"); diff --git a/openair2/RRC/LITE/vars.h b/openair2/RRC/LITE/vars.h index 54315047382765fe0d06cc7f65bd43dbcbfaa626..71b00b278c1124780fb9ee8ed0df24dc87229bd7 100644 --- a/openair2/RRC/LITE/vars.h +++ b/openair2/RRC/LITE/vars.h @@ -80,7 +80,7 @@ struct LogicalChannelConfig__ul_SpecificParameters LCSRB2 = {3, }; -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) struct LogicalChannelConfig__ext1 logicalChannelSR_Mask_r9_ext1 = { logicalChannelSR_Mask_r9: &logicalChannelSR_Mask_r9 }; @@ -88,14 +88,14 @@ struct LogicalChannelConfig__ext1 logicalChannelSR_Mask_r9_ext1 = { // These are the default SRB configurations from 36.331 (Chapter 9, p. 176-179 in v8.6) LogicalChannelConfig_t SRB1_logicalChannelConfig_defaultValue = {ul_SpecificParameters: &LCSRB1 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , ext1: &logicalChannelSR_Mask_r9_ext1 #endif }; LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue = {ul_SpecificParameters: &LCSRB2 -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) , ext1: &logicalChannelSR_Mask_r9_ext1 #endif diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c index af88b19179727689e4437f7d848a8b530c755b39..e57fab74c48715a4cc3b34780ef378982022c121 100644 --- a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c +++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c @@ -36,7 +36,6 @@ void lfds700_hash_a_cleanup( struct lfds700_hash_a_state *has, /****************************************************************************/ -#pragma warning( disable : 4100 ) static void btree_au_element_cleanup_function( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue ) { @@ -57,5 +56,4 @@ static void btree_au_element_cleanup_function( struct lfds700_btree_au_state *ba return; } -#pragma warning( default : 4100 ) diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c index ce2ee825aac80a2358d34ac7f29aeb721c75cb1e..86472b004e2916b99124abb6f91d3b25afa35e70 100644 --- a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c +++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c @@ -154,7 +154,6 @@ void lfds700_list_asu_insert_at_end( struct lfds700_list_asu_state *lasus, /****************************************************************************/ -#pragma warning( disable : 4100 ) void lfds700_list_asu_insert_after_element( struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue, @@ -189,5 +188,4 @@ void lfds700_list_asu_insert_after_element( struct lfds700_list_asu_state *lasus return; } -#pragma warning( default : 4100 ) diff --git a/openair2/UTIL/LISTS/list2.c b/openair2/UTIL/LISTS/list2.c index abd9d2aacce6b139df6ef993ec70cf4a82ff3137..8daa19bfa4515c3b00adb7deddfa90966655c9bd 100644 --- a/openair2/UTIL/LISTS/list2.c +++ b/openair2/UTIL/LISTS/list2.c @@ -233,6 +233,8 @@ list2_add_head (mem_block_t * elementP, list2_t * listP) // almost one element if (head == NULL) { + elementP->previous = NULL; + elementP->next = NULL; listP->head = elementP; listP->tail = elementP; } else { diff --git a/openair2/UTIL/LOG/log.c b/openair2/UTIL/LOG/log.c index 49f00325f8c70d528bf6c1f3cc700928d0cbc601..9c28c4b68d0900afb21775314102bbeb9199b2f0 100644 --- a/openair2/UTIL/LOG/log.c +++ b/openair2/UTIL/LOG/log.c @@ -28,6 +28,7 @@ */ +#define _GNU_SOURCE /* required for pthread_getname_np */ //#define LOG_TEST 1 #define COMPONENT_LOG @@ -124,6 +125,7 @@ int logInit (void) #endif } + #if ! defined(CN_BUILD) g_log->log_component[PHY].name = "PHY"; g_log->log_component[PHY].level = LOG_EMERG; @@ -1031,6 +1033,19 @@ void logRecord_mt(const char *file, const char *func, int line, int comp, if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL; } + if ( (g_log->flag & FLAG_THREAD) || (c->flag & FLAG_THREAD) ) { +# define THREAD_NAME_LEN 128 + char threadname[THREAD_NAME_LEN]; + if (pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN) != 0) + { + perror("pthread_getname_np : "); + } else { + len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]", threadname); + if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL; + } +# undef THREAD_NAME_LEN + } + if ( (g_log->flag & FLAG_FUNCT) || (c->flag & FLAG_FUNCT) ) { len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s] ", func); @@ -1286,11 +1301,15 @@ int set_comp_log(int component, int level, int verbosity, int interval) LOG_EMERG); DevCheck((interval > 0) && (interval <= 0xFF), interval, 0, 0xFF); +#if 0 if ((verbosity == LOG_NONE) || (verbosity == LOG_LOW) || (verbosity == LOG_MED) || (verbosity == LOG_FULL) || (verbosity == LOG_HIGH)) { g_log->log_component[component].flag = verbosity; } +#else + g_log->log_component[component].flag = verbosity; +#endif g_log->log_component[component].level = level; g_log->log_component[component].interval = interval; diff --git a/openair2/UTIL/LOG/log.h b/openair2/UTIL/LOG/log.h index 6a6569c1a585499bb314574cb70a0d26a35d4e36..5140a08dbd4489b77c7ca86b5aeb2383a82277b7 100644 --- a/openair2/UTIL/LOG/log.h +++ b/openair2/UTIL/LOG/log.h @@ -43,6 +43,13 @@ #include <sys/stat.h> #include <fcntl.h> #include <stdarg.h> +#include <time.h> +#include <stdint.h> +#include <inttypes.h> +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <pthread.h> #else #include "rtai_fifos.h" #endif @@ -76,41 +83,197 @@ extern "C" { * @ingroup _macro * @brief LOG defines 9 levels of messages for users. Importance of these levels decrease gradually from 0 to 8 * @{*/ -#ifndef LOG_EMERG # define LOG_EMERG 0 /*!< \brief system is unusable */ -#endif -#ifndef LOG_ALERT # define LOG_ALERT 1 /*!< \brief action must be taken immediately */ -#endif -#ifndef LOG_CRIT # define LOG_CRIT 2 /*!< \brief critical conditions */ -#endif -#ifndef LOG_ERR # define LOG_ERR 3 /*!< \brief error conditions */ -#endif -#ifndef LOG_WARNING # define LOG_WARNING 4 /*!< \brief warning conditions */ -#endif -#ifndef LOG_NOTICE # define LOG_NOTICE 5 /*!< \brief normal but significant condition */ -#endif -#ifndef LOG_INFO # define LOG_INFO 6 /*!< \brief informational */ -#endif -#ifndef LOG_DEBUG # define LOG_DEBUG 7 /*!< \brief debug-level messages */ -#endif -#ifndef LOG_FILE # define LOG_FILE 8 /*!< \brief message sequence chart -level */ -#endif -#ifndef LOG_TRACE # define LOG_TRACE 9 /*!< \brief trace-level messages */ -#endif - #define NUM_LOG_LEVEL 10 /*!< \brief the number of message levels users have with LOG */ /* @}*/ +/** @defgroup _log_format Defined log format + * @ingroup _macro + * @brief Macro of log formats defined by LOG + * @{*/ + +/* .log_format = 0x13 uncolored standard messages + * .log_format = 0x93 colored standard messages */ + +#define LOG_RED "\033[1;31m" /*!< \brief VT100 sequence for bold red foreground */ +#define LOG_GREEN "\033[32m" /*!< \brief VT100 sequence for green foreground */ +#define LOG_ORANGE "\033[93m" /*!< \brief VT100 sequence for orange foreground */ +#define LOG_BLUE "\033[34m" /*!< \brief VT100 sequence for blue foreground */ +#define LOG_CYBL "\033[40;36m" /*!< \brief VT100 sequence for cyan foreground on black background */ +#define LOG_RESET "\033[0m" /*!< \brief VT100 sequence for reset (black) foreground */ +/* @}*/ + + +/** @defgroup _syslog_conf Macros for write in syslog.conf + * @ingroup _macro + * @brief Macros used to write lines (local/remote) in syslog.conf + * @{*/ +#define LOG_LOCAL 0x01 +#define LOG_REMOTE 0x02 + +#define FLAG_COLOR 0x001 /*!< \brief defaults */ +#define FLAG_PID 0x002 /*!< \brief defaults */ +#define FLAG_COMP 0x004 +#define FLAG_THREAD 0x008 /*!< \brief all : 255/511 */ +#define FLAG_LEVEL 0x010 +#define FLAG_FUNCT 0x020 +#define FLAG_FILE_LINE 0x040 +#define FLAG_TIME 0x100 + +#define LOG_NONE 0x00 +#define LOG_LOW 0x5 +#define LOG_MED 0x15 +#define LOG_HIGH 0x35 +#define LOG_FULL 0x75 + +#define OAI_OK 0 /*!< \brief all ok */ +#define OAI_ERR 1 /*!< \brief generic error */ +#define OAI_ERR_READ_ONLY 2 /*!< \brief tried to write to read-only item */ +#define OAI_ERR_NOTFOUND 3 /*!< \brief something wasn't found */ +/* @}*/ + + +//static char *log_level_highlight_start[] = {LOG_RED, LOG_RED, LOG_RED, LOG_RED, LOG_BLUE, "", "", "", LOG_GREEN}; /*!< \brief Optional start-format strings for highlighting */ + +//static char *log_level_highlight_end[] = {LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, "", "", "", LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */ + +typedef enum { + MIN_LOG_COMPONENTS = 0, + PHY = MIN_LOG_COMPONENTS, + MAC, + EMU, + OCG, + OMG, + OPT, + OTG, + OTG_LATENCY, + OTG_LATENCY_BG, + OTG_GP, + OTG_GP_BG, + OTG_JITTER, + RLC, + PDCP, + RRC, + NAS, + PERF, + OIP, + CLI, + MSC, + OCM, + UDP_, + GTPU, + SPGW, + S1AP, + SCTP, + HW, + OSA, + RAL_ENB, + RAL_UE, + ENB_APP, + FLEXRAN_AGENT, + TMR, + USIM, + LOCALIZE, + RRH, + X2AP, + MAX_LOG_COMPONENTS, +} +comp_name_t; + +//#define msg printf + +typedef struct { + char *name; /*!< \brief string name of item */ + int value; /*!< \brief integer value of mapping */ +} mapping; + + +typedef struct { + const char *name; + int level; + int flag; + int interval; + int fd; + int filelog; + char *filelog_name; + + /* SR: make the log buffer component relative */ + char log_buffer[MAX_LOG_TOTAL]; +} log_component_t; + +typedef struct { + unsigned int remote_ip; + unsigned int audit_ip; + int remote_level; + int facility; + int audit_facility; + int format; +} log_config_t; + + +typedef struct { + log_component_t log_component[MAX_LOG_COMPONENTS]; + log_config_t config; + char* level2string[NUM_LOG_LEVEL]; + int level; + int onlinelog; + int flag; + int syslog; + int filelog; + char* filelog_name; +} log_t; + +typedef struct LOG_params { + const char *file; + const char *func; + int line; + int comp; + int level; + const char *format; + char l_buff_info [MAX_LOG_INFO]; + int len; +} LOG_params; + +#if defined(ENABLE_ITTI) +typedef enum log_instance_type_e { + LOG_INSTANCE_UNKNOWN, + LOG_INSTANCE_ENB, + LOG_INSTANCE_UE, +} log_instance_type_t; + +void log_set_instance_type (log_instance_type_t instance); +#endif + + +/*--- INCLUDES ---------------------------------------------------------------*/ +# include "log_if.h" +/*----------------------------------------------------------------------------*/ +int logInit (void); +void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7))); +void logRecord(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7))); +int set_comp_log(int component, int level, int verbosity, int interval); +int set_log(int component, int level, int interval); +void set_glog(int level, int verbosity); +void set_log_syslog(int enable); +void set_log_onlinelog(int enable); +void set_log_filelog(int enable); +void set_component_filelog(int comp); +int map_str_to_int(mapping *map, const char *str); +char *map_int_to_str(mapping *map, int val); +void logClean (void); +int is_newline( char *str, int size); +void *log_thread_function(void * list); + /** @defgroup _logIt logIt function * @ingroup _macro * @brief Macro used to call tr_log_full_ex with file, function and line information @@ -186,169 +349,107 @@ extern "C" { #define LOG_RETURN(c,x) do {uint32_t __rv;__rv=(unsigned int)(x);LOG_T(c,"Returning %08x\n", __rv);return((typeof(x))__rv);}while(0) /*!< \brief Macro to log a function exit, including integer value, then to return a value to the calling function */ /* @}*/ - -/** @defgroup _log_format Defined log format - * @ingroup _macro - * @brief Macro of log formats defined by LOG - * @{*/ - -/* .log_format = 0x13 uncolored standard messages - * .log_format = 0x93 colored standard messages */ - -#define LOG_RED "\033[1;31m" /*!< \brief VT100 sequence for bold red foreground */ -#define LOG_GREEN "\033[32m" /*!< \brief VT100 sequence for green foreground */ -#define LOG_ORANGE "\033[93m" /*!< \brief VT100 sequence for orange foreground */ -#define LOG_BLUE "\033[34m" /*!< \brief VT100 sequence for blue foreground */ -#define LOG_CYBL "\033[40;36m" /*!< \brief VT100 sequence for cyan foreground on black background */ -#define LOG_RESET "\033[0m" /*!< \brief VT100 sequence for reset (black) foreground */ -/* @}*/ - - -/** @defgroup _syslog_conf Macros for write in syslog.conf - * @ingroup _macro - * @brief Macros used to write lines (local/remote) in syslog.conf - * @{*/ -#define LOG_LOCAL 0x01 -#define LOG_REMOTE 0x02 - -#define FLAG_COLOR 0x001 /*!< \brief defaults */ -#define FLAG_PID 0x002 /*!< \brief defaults */ -#define FLAG_COMP 0x004 -#define FLAG_THREAD 0x008 /*!< \brief all : 255/511 */ -#define FLAG_LEVEL 0x010 -#define FLAG_FUNCT 0x020 -#define FLAG_FILE_LINE 0x040 -#define FLAG_TIME 0x100 - -#define LOG_NONE 0x00 -#define LOG_LOW 0x5 -#define LOG_MED 0x15 -#define LOG_HIGH 0x35 -#define LOG_FULL 0x75 - -#define OAI_OK 0 /*!< \brief all ok */ -#define OAI_ERR 1 /*!< \brief generic error */ -#define OAI_ERR_READ_ONLY 2 /*!< \brief tried to write to read-only item */ -#define OAI_ERR_NOTFOUND 3 /*!< \brief something wasn't found */ -/* @}*/ - - -//static char *log_level_highlight_start[] = {LOG_RED, LOG_RED, LOG_RED, LOG_RED, LOG_BLUE, "", "", "", LOG_GREEN}; /*!< \brief Optional start-format strings for highlighting */ - -//static char *log_level_highlight_end[] = {LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, "", "", "", LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */ - -typedef enum { - MIN_LOG_COMPONENTS = 0, - PHY = MIN_LOG_COMPONENTS, - MAC, - EMU, - OCG, - OMG, - OPT, - OTG, - OTG_LATENCY, - OTG_LATENCY_BG, - OTG_GP, - OTG_GP_BG, - OTG_JITTER, - RLC, - PDCP, - RRC, - NAS, - PERF, - OIP, - CLI, - MSC, - OCM, - UDP_, - GTPU, - SPGW, - S1AP, - SCTP, - HW, - OSA, - RAL_ENB, - RAL_UE, - ENB_APP, - FLEXRAN_AGENT, - TMR, - USIM, - LOCALIZE, - RRH, - X2AP, - MAX_LOG_COMPONENTS, +static __inline__ uint64_t rdtsc(void) { + uint64_t a, d; + __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); + return (d<<32) | a; } -comp_name_t; - -//#define msg printf - -typedef struct { - char *name; /*!< \brief string name of item */ - int value; /*!< \brief integer value of mapping */ -} mapping; - -typedef struct { - const char *name; - int level; - int flag; - int interval; - int fd; - int filelog; - char *filelog_name; - - /* SR: make the log buffer component relative */ - char log_buffer[MAX_LOG_TOTAL]; -} log_component_t; - -typedef struct { - unsigned int remote_ip; - unsigned int audit_ip; - int remote_level; - int facility; - int audit_facility; - int format; -} log_config_t; +#define DEBUG_REALTIME 1 +#if DEBUG_REALTIME + +extern double cpuf; + +static inline uint64_t checkTCPU(int timeout, char * file, int line) { + static uint64_t __thread lastCPUTime=0; + static uint64_t __thread last=0; + uint64_t cur=rdtsc(); + struct timespec CPUt; + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &CPUt); + uint64_t CPUTime=CPUt.tv_sec*1000*1000+CPUt.tv_nsec/1000; + double microCycles=(double)(cpuf*1000); + int duration=(int)((cur-last)/microCycles); + if ( last!=0 && duration > timeout ) { + //struct timespec ts; + //clock_gettime(CLOCK_MONOTONIC, &ts); + printf("%s:%d lte-ue delay %d (exceed %d), CPU for this period: %lld\n", file, line, + duration, timeout, (long long)CPUTime-lastCPUTime ); + } + last=cur; + lastCPUTime=CPUTime; + return cur; +} +static inline unsigned long long checkT(int timeout, char * file, int line) { + static unsigned long long __thread last=0; + unsigned long long cur=rdtsc(); + int microCycles=(int)(cpuf*1000); + int duration=(int)((cur-last)/microCycles); + if ( last!=0 && duration > timeout ) + printf("%s:%d lte-ue delay %d (exceed %d)\n", file, line, + duration, timeout); + last=cur; + return cur; +} -typedef struct { - log_component_t log_component[MAX_LOG_COMPONENTS]; - log_config_t config; - char* level2string[NUM_LOG_LEVEL]; - int level; - int onlinelog; - int flag; - int syslog; - int filelog; - char* filelog_name; -} log_t; +typedef struct m { + uint64_t iterations; + uint64_t sum; + uint64_t maxArray[11]; +} Meas; + +static inline void printMeas(char * txt, Meas *M, int period) { + if (M->iterations%period == 0 ) { + char txt2[512]; + sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " max=%" + PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n", + txt, + M->sum/M->iterations, + M->iterations, + M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5], + M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]); + LOG_W(PHY,"%s",txt2); + } +} -typedef struct LOG_params { - const char *file; - const char *func; - int line; - int comp; - int level; - const char *format; - char l_buff_info [MAX_LOG_INFO]; - int len; -} LOG_params; +static inline int cmpint(const void* a, const void* b) { + uint64_t* aa=(uint64_t*)a; + uint64_t* bb=(uint64_t*)b; + return (int)(*aa-*bb); +} +static inline void updateTimes(uint64_t start, Meas *M, int period, char * txt) { + if (start!=0) { + uint64_t end=rdtsc(); + long long diff=(end-start)/(cpuf*1000); + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + printMeas(txt,M,period); + } +} -#if defined(ENABLE_ITTI) -typedef enum log_instance_type_e { - LOG_INSTANCE_UNKNOWN, - LOG_INSTANCE_ENB, - LOG_INSTANCE_UE, -} log_instance_type_t; +#define check(a) do { checkT(a,__FILE__,__LINE__); } while (0) +#define checkcpu(a) do { checkTCPU(a,__FILE__,__LINE__); } while (0) +#define initRefTimes(a) static __thread Meas a= {0} +#define pickTime(a) uint64_t a=rdtsc() +#define readTime(a) a +#define initStaticTime(a) static __thread uint64_t a={0} +#define pickStaticTime(a) do { a=rdtsc(); } while (0) -void log_set_instance_type (log_instance_type_t instance); +#else +#define check(a) do {} while (0) +#define checkcpu(a) do {} while (0) +#define initRefTimes(a) do {} while (0) +#define initStaticTime(a) do {} while (0) +#define pickTime(a) do {} while (0) +#define readTime(a) 0 +#define pickStaticTime(a) do {} while (0) +#define updateTimes(a,b,c,d) do {} while (0) +#define printMeas(a,b,c) do {} while (0) #endif -int logInit (void); -/*--- INCLUDES ---------------------------------------------------------------*/ -# include "log_if.h" -/*----------------------------------------------------------------------------*/ #ifdef __cplusplus } #endif diff --git a/openair2/UTIL/LOG/log_if.h b/openair2/UTIL/LOG/log_if.h index 3dd25ff365350008105946824804991f8982095f..6338fab829cad69385f9471cc331594b65a05cc4 100644 --- a/openair2/UTIL/LOG/log_if.h +++ b/openair2/UTIL/LOG/log_if.h @@ -27,59 +27,8 @@ * \warning This component can be runned only in user-space * @ingroup routing */ -#ifndef __LOG_IF_H__ -# define __LOG_IF_H__ - - -/*--- INCLUDES ---------------------------------------------------------------*/ -# include "log.h" -/*----------------------------------------------------------------------------*/ -#ifdef __cplusplus -extern "C" { -#endif - -# ifdef COMPONENT_LOG -# ifdef COMPONENT_LOG_IF -# define private_log_if(x) x -# define friend_log_if(x) x -# define public_log_if(x) x -# else -# define private_log_if(x) -# define friend_log_if(x) extern x -# define public_log_if(x) extern x -# endif -# else -# define private_log_if(x) -# define friend_log_if(x) -# define public_log_if(x) extern x -# endif - -/** @defgroup _log_if Interfaces of LOG - * @{*/ - -//public_log_if( log_t *g_log;) - -public_log_if( int logInit (void);) -public_log_if( void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));) -public_log_if( void logRecord(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));) -public_log_if( int set_comp_log(int component, int level, int verbosity, int interval);) -public_log_if( int set_log(int component, int level, int interval);) -public_log_if( void set_glog(int level, int verbosity);) -public_log_if( void set_log_syslog(int enable);) -public_log_if( void set_log_onlinelog(int enable);) -public_log_if( void set_log_filelog(int enable);) -public_log_if( void set_component_filelog(int comp);) -public_log_if( int map_str_to_int(mapping *map, const char *str);) -public_log_if( char *map_int_to_str(mapping *map, int val);) -public_log_if( void logClean (void); ) -public_log_if( int is_newline( char *str, int size);) -public_log_if( void *log_thread_function(void * list);) - -/* @}*/ - -#ifdef __cplusplus -} -#endif - -#endif +// LTS: kept this file for compatibility +// this file was probably a trial to separate internal functions and external ones +// but it has never been finished, most source code include directly log.h (not log_if.h) +#include "log.h" diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 96f173833ae9d911070280faed4b13ca6a986f85..88508adac3fcd8317a25d2bd24c8a364bbb6019d 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -181,6 +181,10 @@ const char* eurecomVariablesNames[] = { "ue0_trx_write_ns", "ue0_trx_read_ns_missing", "ue0_trx_write_ns_missing" + "send_if4_symbol", + "recv_if4_symbol", + "send_if5_pkt_id", + "recv_if5_pkt_id" }; const char* eurecomFunctionsNames[] = { @@ -375,7 +379,10 @@ const char* eurecomFunctionsNames[] = { "send_if4", "recv_if4", "send_if5", - "recv_if5" + "recv_if5", + + "compress_if", + "decompress_if" }; struct vcd_module_s vcd_modules[VCD_SIGNAL_DUMPER_MODULE_END] = { diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index e1bcff39fcb63c69aed24ff5a1da9e26830284a1..fde3d429ea59b26265bf01685ec7c63facb1bc1e 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -147,6 +147,10 @@ typedef enum { VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN5, VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN6, VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN7, + VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF4_SYMBOL, + VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF4_SYMBOL, + VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, + VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_SIZE, VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_ERR, VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, @@ -354,6 +358,9 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, + VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, + VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, + VCD_SIGNAL_DUMPER_FUNCTIONS_LAST, VCD_SIGNAL_DUMPER_FUNCTIONS_END = VCD_SIGNAL_DUMPER_FUNCTIONS_LAST, } vcd_signal_dump_functions; diff --git a/openair2/UTIL/OMV/structures.h b/openair2/UTIL/OMV/structures.h index c50e7b22973c05f7c1c212485685ad955d59a137..434fa4c3836e888697328ae182b422b78fb1d1b0 100644 --- a/openair2/UTIL/OMV/structures.h +++ b/openair2/UTIL/OMV/structures.h @@ -31,13 +31,12 @@ #ifndef STRUCTURES_H #define STRUCTURES_H +#include "openairinterface5g_limits.h" #ifndef __PHY_IMPLEMENTATION_DEFS_H__ -#define Maxneighbor 64 -#define NUMBER_OF_UE_MAX 64 -#define NUMBER_OF_eNB_MAX 3 -#ifndef NB_ANTENNAS_RX -# define NB_ANTENNAS_RX 4 -#endif + #define Maxneighbor NUMBER_OF_UE_MAX + #ifndef NB_ANTENNAS_RX + #define NB_ANTENNAS_RX 4 + #endif #endif // diff --git a/openair2/UTIL/OTG/otg_defs.h b/openair2/UTIL/OTG/otg_defs.h index 0cef777b8f0b98eddeb42b61323bc985ff1e9b6b..ebb3f299897031f17ae140f61091d177121aae60 100644 --- a/openair2/UTIL/OTG/otg_defs.h +++ b/openair2/UTIL/OTG/otg_defs.h @@ -33,12 +33,12 @@ #ifndef __OTG_DEFS_H__ # define __OTG_DEFS_H__ - +/* \brief To define the NUMBER_OF_eNB_MAX and NUMBER_OF_UE_MAX */ #if STANDALONE==1 -# define NUMBER_OF_eNB_MAX 3 -# define NUMBER_OF_UE_MAX 3 + #include "openairinterface5g_limits.h" #else -#include "PHY/impl_defs_top.h" /* \brief To define the NUMBER_OF_eNB_MAX and NUMBER_OF_UE_MAX */ + // impl_defs_top.h includes openairinterface5g_limits.h + #include "PHY/impl_defs_top.h" #endif #include "otg_config.h" diff --git a/openair2/UTIL/OTG/otg_rx_socket.c b/openair2/UTIL/OTG/otg_rx_socket.c index 2caeee4f5274bcf30b2bebe0071acd1a110dda24..98e03532a15403982f9c1560d46cd3ab1beae798 100644 --- a/openair2/UTIL/OTG/otg_rx_socket.c +++ b/openair2/UTIL/OTG/otg_rx_socket.c @@ -98,7 +98,7 @@ void *recv_ip4_tcp(void* csock) LOG_I(OTG,"SOCKET:: TCP-IP4 :: size=%d received=%d, Received buffer: %s \n\n\n", strlen(buffer), sock_rcv, buffer); - buffer[PAYLOAD_MAX] != '\0'; + //buffer[PAYLOAD_MAX] != '\0'; } diff --git a/openair3/NAS/COMMON/EMM/MSG/emm_msg.c b/openair3/NAS/COMMON/EMM/MSG/emm_msg.c index b067b9c0d1584929fdcab190bca92de17e470af9..c357e8784f803827e9e83041033472d1b571bb86 100644 --- a/openair3/NAS/COMMON/EMM/MSG/emm_msg.c +++ b/openair3/NAS/COMMON/EMM/MSG/emm_msg.c @@ -464,6 +464,9 @@ int emm_msg_encode(EMM_msg *msg, uint8_t *buffer, uint32_t len) #endif } + if (encode_result < 0) + LOG_FUNC_RETURN (encode_result); + LOG_FUNC_RETURN (header_result + encode_result); } diff --git a/openair3/NAS/COMMON/UTIL/memory.c b/openair3/NAS/COMMON/UTIL/memory.c index df94d40cfcc7a89d9d1c343e184c8e87b798d775..3b3b6e7f9e1d47caf3e5a2f4736a38eb9f8a1e4b 100644 --- a/openair3/NAS/COMMON/UTIL/memory.c +++ b/openair3/NAS/COMMON/UTIL/memory.c @@ -103,6 +103,30 @@ char* memory_get_path(const char* dirname, const char* filename) return data_filename; } +char* memory_get_path_from_ueid(const char* dirname, const char* filename, int ueid) +{ + /* Get non-volatile data directory */ + const char* path = getenv(dirname); + char buffer[2048]; + + if (path == NULL) { + path = getenv(DEFAULT_NAS_PATH); + } + + if (path == NULL) { + LOG_TRACE(WARNING, "MEMORY - %s and %s environment variables are not defined trying local directory", dirname, DEFAULT_NAS_PATH); + path = "."; + } + + /* Append non-volatile data file name */ + if ( snprintf(buffer, sizeof(buffer), "%s/%s%d", path, filename, ueid) < 0 ) { + return NULL; + } + + return strdup(buffer); +} + + /**************************************************************************** ** ** ** Name: memory_read() ** diff --git a/openair3/NAS/COMMON/UTIL/memory.h b/openair3/NAS/COMMON/UTIL/memory.h index f41f4d586b51b9aaf32df5031700cbb423ba51c9..f7f0733044b50163c262036e5cc0abd9cc85fdc6 100644 --- a/openair3/NAS/COMMON/UTIL/memory.h +++ b/openair3/NAS/COMMON/UTIL/memory.h @@ -58,6 +58,8 @@ Description Memory access utilities char* memory_get_path(const char* dirname, const char* filename); +char* memory_get_path_from_ueid(const char* dirname, const char* filename, int ueid); + int memory_read(const char* datafile, void* data, size_t size); int memory_write(const char* datafile, const void* data, size_t size); diff --git a/openair3/NAS/COMMON/commonDef.h b/openair3/NAS/COMMON/commonDef.h index 64216b009465119c56e0d357dab48875b7c4be08..84d97fc4a8cb954386d0bd7976d5b11630f1d084 100644 --- a/openair3/NAS/COMMON/commonDef.h +++ b/openair3/NAS/COMMON/commonDef.h @@ -314,6 +314,7 @@ typedef struct { */ #define TAI_LIST_T(SIZE) struct {Byte_t n_tais; tai_t tai[SIZE];} +#if 0 /* * User notification callback, executed whenever a change of data with * respect of network information (e.g. network registration and/or @@ -322,6 +323,7 @@ typedef struct { */ typedef int (*emm_indication_callback_t) (Stat_t, tac_t, ci_t, AcT_t, const char*, size_t); +#endif typedef enum eps_protocol_discriminator_e { /* Protocol discriminator identifier for EPS Mobility Management */ diff --git a/openair3/NAS/COMMON/networkDef.h b/openair3/NAS/COMMON/networkDef.h index 46716bee24714ab2273744c4634a0924d9320207..e3e8e1f08b3487d6613dcbbf450b810204f01aaf 100644 --- a/openair3/NAS/COMMON/networkDef.h +++ b/openair3/NAS/COMMON/networkDef.h @@ -260,12 +260,14 @@ typedef struct { network_pkf_t* pkf[NET_PACKET_FILTER_MAX]; } network_tft_t; +#if 0 /* * User notification callback, executed whenever a change of status with * respect of PDN connection or EPS bearer context is notified by the EPS * Session Management sublayer */ typedef int (*esm_indication_callback_t) (int, network_pdn_state_t); +#endif /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ diff --git a/openair3/NAS/TEST/NETWORK/README b/openair3/NAS/TEST/NETWORK/README index 25a6de5d147600feaa5b5d0f2edabcf73bb27477..465e355e784ff3a7f529d22a8487dac5cd9d486e 100644 --- a/openair3/NAS/TEST/NETWORK/README +++ b/openair3/NAS/TEST/NETWORK/README @@ -18,9 +18,9 @@ EURECOM-NAS directory should contain following files: EURECOM-NAS |-- bin -| |-- .ue.nvram -| |-- .ue_emm.nvram -| |-- .usim.nvram +| |-- .ue.nvram0 +| |-- .ue_emm.nvram0 +| |-- .usim.nvram0 | |-- NetworkProcess | |-- UEprocess | `-- UserProcess @@ -57,10 +57,10 @@ UE for testing purpose. When starting up, UEprocess reads configuration data from .nvram binary files used as UE's non-volatile memory. -.usim.nvram contains data stored into the USIM -.ue.nvram contains data related to the UE identification (IMEI, +.usim.nvram0 contains data stored into the USIM +.ue.nvram0 contains data related to the UE identification (IMEI, manufacturer, model, PIN code) -.ue_emm.nvram contains data related to EPS Mobility Management (IMSI, last +.ue_emm.nvram0 contains data related to EPS Mobility Management (IMSI, last registered PLMN) -------------------------------------------------------------------------------- diff --git a/openair3/NAS/TOOLS/Makefile b/openair3/NAS/TOOLS/Makefile deleted file mode 100644 index ca2e884c1110f9d3fa6e53e0e9df0fd0f2bfb509..0000000000000000000000000000000000000000 --- a/openair3/NAS/TOOLS/Makefile +++ /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.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.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 -# */ - -export PROCESS = UE - -ifndef PROJDIR -PROJDIR = $(PWD)/.. -endif - -include $(PROJDIR)/Makerules -include $(PROJDIR)/Makefile.inc -include $(PROJDIR)/../Makefile.tools - -export LD_RUN_PATH = $(LIBDIR):$(LIBPROCESS) - -LIBS = -luenas.a -lrt -INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(USIMAPIDIR) -I$(EMMDIR) -I$(ESMDIR) -I$(IESDIR) - -#LIBSUTIL = $(LIBDIR)/$(LIBUTIL).a $(LIBDIR)/$(LIBUTIL).so - -USIM_OBJ = usim_data.o -UE_OBJ = ue_data.o - -USIM_TARGET = usim_data -UE_TARGET = ue_data - -TARGETS = $(USIM_TARGET) $(UE_TARGET) - -all: $(TARGETS) - -#-DIMSI_USA_MNC_3DIGITS -%.o: %.c Makefile - $(CC) $(CFLAGS) -c $< -o $@ - -$(USIM_TARGET): $(USIM_OBJ) $(LIBSUTIL) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lnettle -lcrypto -lm - @echo Replacing $@ to $(BINDIR) - @$(RM) $(BINDIR)/$@ - @$(CP) $@ $(BINDIR) - -$(UE_TARGET): $(UE_OBJ) $(LIBSUTIL) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lnettle -lcrypto -lm - @echo Replacing $@ to $(BINDIR) - @$(RM) $(BINDIR)/$@ - @$(CP) $@ $(BINDIR) - -clean: - $(RM) $(OBJS) *.bak *~ - -veryclean: clean - $(RM) $(TARGETS) - -veryveryclean: veryclean - $(RM) -Rf *.o $(PROJDIR) - $(RM) -Rf *.a $(PROJDIR) - -depend: - makedepend -- ${CFLAGS} -- ${SRCS} - -# DO NOT DELETE THIS LINE -- make depend depends on it. - diff --git a/openair3/NAS/TOOLS/conf2uedata.c b/openair3/NAS/TOOLS/conf2uedata.c new file mode 100644 index 0000000000000000000000000000000000000000..80a6933c05b080d7125284efab0f62734fe3e630 --- /dev/null +++ b/openair3/NAS/TOOLS/conf2uedata.c @@ -0,0 +1,62 @@ +#include <stdio.h> // perror, printf, fprintf, snprintf +#include <stdlib.h> // exit, free +#include <string.h> // memset, strncpy +#include <getopt.h> + +#include "conf2uedata.h" +#include "display.h" +#include "conf_parser.h" + +int main(int argc, char**argv) { + int option; + const char* conf_file = NULL; + const char* output_dir = NULL; + const char options[]="c:o:h"; + + while ((option = getopt(argc, argv, options)) != -1) { + switch (option) { + case 'c': + conf_file = optarg; + break; + case 'o': + output_dir = optarg; + break; + case 'h': + _display_usage(); + return true; + break; + default: + break; + } + } + + if (output_dir == NULL ) { + printf("No output option found\n"); + _display_usage(); + exit(1); + } + + if ( conf_file == NULL ) { + printf("No Configuration file is given\n"); + _display_usage(); + exit(1); + } + + if ( parse_config_file(output_dir, conf_file, OUTPUT_ALL) == false ) { + exit(1); + } + + display_data_from_directory(output_dir, DISPLAY_ALL); + + exit(0); +} + +/* + * Displays command line usage + */ +void _display_usage(void) { + fprintf(stderr, "usage: conf2uedata [OPTION]...\n"); + fprintf(stderr, "\t[-c]\tConfig file to use\n"); + fprintf(stderr, "\t[-o]\toutput file directory\n"); + fprintf(stderr, "\t[-h]\tDisplay this usage\n"); +} diff --git a/openair3/NAS/TOOLS/conf2uedata.h b/openair3/NAS/TOOLS/conf2uedata.h new file mode 100644 index 0000000000000000000000000000000000000000..ed56a22718fb96ba16c892d089d0ba1560a77a3b --- /dev/null +++ b/openair3/NAS/TOOLS/conf2uedata.h @@ -0,0 +1,6 @@ +#ifndef _CONF2UEDATA_H +#define _CONF2UEDATA_H + +void _display_usage(void); + +#endif // _CONF2UEDATA_H diff --git a/openair3/NAS/TOOLS/conf_emm.c b/openair3/NAS/TOOLS/conf_emm.c new file mode 100644 index 0000000000000000000000000000000000000000..668b90a0ae0514de07872b092789c68b5a187773 --- /dev/null +++ b/openair3/NAS/TOOLS/conf_emm.c @@ -0,0 +1,88 @@ +#include <string.h> + +#include "memory.h" +#include "conf_emm.h" +#include "fs.h" + +void gen_emm_data( + emm_nvdata_t *emm_data, + const char *hplmn, + const char *msin, + const plmns_list *eplmn, + const networks_t networks) +{ + memset(emm_data, 0, sizeof(emm_nvdata_t)); + int hplmn_index = get_plmn_index(hplmn, networks); + plmn_conf_param_t *conf = &networks.items[hplmn_index].conf; + int i; + + emm_data->imsi.length = 8; + emm_data->imsi.u.num.parity = get_msin_parity(msin, conf->mcc, conf->mnc); + emm_data->imsi.u.num.digit1 = conf->mcc[0]; + emm_data->imsi.u.num.digit2 = conf->mcc[1]; + emm_data->imsi.u.num.digit3 = conf->mcc[2]; + + emm_data->imsi.u.num.digit4 = conf->mnc[0]; + emm_data->imsi.u.num.digit5 = conf->mnc[1]; + + if (strlen(conf->mnc) == 3) { + emm_data->rplmn.MNCdigit3 = conf->mnc[2]; + + emm_data->imsi.u.num.digit6 = conf->mnc[2]; + emm_data->imsi.u.num.digit7 = msin[0]; + emm_data->imsi.u.num.digit8 = msin[1]; + emm_data->imsi.u.num.digit9 = msin[2]; + emm_data->imsi.u.num.digit10 = msin[3]; + emm_data->imsi.u.num.digit11 = msin[4]; + emm_data->imsi.u.num.digit12 = msin[5]; + emm_data->imsi.u.num.digit13 = msin[6]; + emm_data->imsi.u.num.digit14 = msin[7]; + emm_data->imsi.u.num.digit15 = msin[8]; + } else { + emm_data->rplmn.MNCdigit3 = 0xf; + + emm_data->imsi.u.num.digit6 = msin[0]; + emm_data->imsi.u.num.digit7 = msin[1]; + emm_data->imsi.u.num.digit8 = msin[2]; + emm_data->imsi.u.num.digit9 = msin[3]; + emm_data->imsi.u.num.digit10 = msin[4]; + emm_data->imsi.u.num.digit11 = msin[5]; + emm_data->imsi.u.num.digit12 = msin[6]; + emm_data->imsi.u.num.digit13 = msin[7]; + emm_data->imsi.u.num.digit14 = msin[8]; + emm_data->imsi.u.num.digit15 = msin[9]; + } + + emm_data->rplmn.MCCdigit1 = conf->mcc[0]; + emm_data->rplmn.MCCdigit2 = conf->mcc[1]; + emm_data->rplmn.MCCdigit3 = conf->mcc[2]; + emm_data->rplmn.MNCdigit1 = conf->mnc[0]; + emm_data->rplmn.MNCdigit2 = conf->mnc[1]; + + emm_data->eplmn.n_plmns = eplmn->size; + for (i = 0; i < eplmn->size; i++) { + emm_data->eplmn.plmn[i] = networks.items[eplmn->items[i]].plmn; + } +} + +bool write_emm_data(const char *directory, int user_id, emm_nvdata_t *emm_data) { + int rc; + char* filename = make_filename(directory, EMM_NVRAM_FILENAME, user_id); + rc = memory_write(filename, emm_data, sizeof(emm_nvdata_t)); + free(filename); + if (rc != RETURNok) { + perror("ERROR\t: memory_write() failed"); + exit(false); + } + return(true); +} + +int get_msin_parity(const char * msin, const char *mcc, const char *mnc) { + int imsi_size = strlen(msin) + strlen(mcc) + + strlen(mnc); + int result = (imsi_size % 2 == 0) ? 0 : 1; + return result; + +} + + diff --git a/openair3/NAS/TOOLS/conf_emm.h b/openair3/NAS/TOOLS/conf_emm.h new file mode 100644 index 0000000000000000000000000000000000000000..f9c30d31c9523f2bb67ab27c6722883de76d52ba --- /dev/null +++ b/openair3/NAS/TOOLS/conf_emm.h @@ -0,0 +1,18 @@ +#ifndef _CONF_EMM_H +#define _CONF_EMM_H + +#include "emmData.h" +#include "conf_network.h" +#include "conf_user_plmn.h" + +void gen_emm_data( + emm_nvdata_t *emm_data, + const char *hplmn, + const char *msin, + const plmns_list *eplmn, + const networks_t networks); + +bool write_emm_data(const char *directory, int user_id, emm_nvdata_t *emm_data); +int get_msin_parity(const char * msin, const char *mcc, const char *mnc); + +#endif diff --git a/openair3/NAS/TOOLS/conf_network.c b/openair3/NAS/TOOLS/conf_network.c new file mode 100644 index 0000000000000000000000000000000000000000..96e2183327ad1c8d35215f898566582efe2ee994 --- /dev/null +++ b/openair3/NAS/TOOLS/conf_network.c @@ -0,0 +1,112 @@ +#include <stdlib.h> +#include <string.h> + +#include "conf_network.h" + +int get_plmn_index(const char * mccmnc, const networks_t networks) { + char mcc[4]; + char mnc[strlen(mccmnc) - 2]; + strncpy(mcc, mccmnc, 3); + mcc[3] = '\0'; + strncpy(mnc, mccmnc + 3, 3); + mnc[strlen(mccmnc) - 3] = '\0'; + for (int i = 0; i < networks.size; i++) { + if (strcmp(networks.items[i].conf.mcc, mcc) == 0) { + if (strcmp(networks.items[i].conf.mnc, mnc) == 0) { + return i; + } + } + } + return -1; +} + +plmn_t make_plmn_from_conf(const plmn_conf_param_t *plmn_conf) { + plmn_t plmn; + char num[6]; + + memset(&plmn, 0xff, sizeof(plmn)); + + snprintf(num, 6, "%s%s", plmn_conf->mcc, plmn_conf->mnc); + + plmn.MCCdigit2 = plmn_conf->mcc[1]; + plmn.MCCdigit1 = plmn_conf->mcc[0]; + plmn.MCCdigit3 = plmn_conf->mcc[2]; + plmn.MNCdigit2 = plmn_conf->mnc[1]; + plmn.MNCdigit1 = plmn_conf->mnc[0]; + if (strlen(plmn_conf->mnc) > 2) { + plmn.MNCdigit3 = plmn_conf->mnc[2]; + } + return plmn; +} + +void gen_network_record_from_conf(const plmn_conf_param_t *conf, network_record_t *record) { + strcpy(record->fullname, conf->fullname); + strcpy(record->shortname, conf->shortname); + + char num[6]; + sprintf(num, "%s%s", conf->mcc, conf->mnc); + record->num = atoi(num); + + record->plmn = make_plmn_from_conf(conf); + record->tac_end = 0xfffd; + record->tac_start = 0x0001; +} + +bool parse_plmn_param(config_setting_t *plmn_setting, plmn_conf_param_t *conf) { + int rc = 0; + rc = config_setting_lookup_string(plmn_setting, FULLNAME, &conf->fullname); + if (rc != 1) { + printf("Error on FULLNAME\n"); + return false; + } + rc = config_setting_lookup_string(plmn_setting, SHORTNAME, &conf->shortname); + if (rc != 1) { + printf("Error on SHORTNAME\n"); + return false; + } + rc = config_setting_lookup_string(plmn_setting, MNC, &conf->mnc); + if (rc != 1 || strlen(conf->mnc) > 3 + || strlen(conf->mnc) < 2) { + printf("Error ond MNC. Exiting\n"); + return false; + } + rc = config_setting_lookup_string(plmn_setting, MCC, &conf->mcc); + if (rc != 1 || strlen(conf->mcc) != 3) { + printf("Error on MCC\n"); + return false; + } + return true; +} + +bool parse_plmns(config_setting_t *all_plmn_setting, networks_t *networks) { + config_setting_t *plmn_setting = NULL; + char plmn[10]; + int size = 0; + + size = config_setting_length(all_plmn_setting); + + networks->size = size; + networks->items = malloc(sizeof(network_t) * size); + for (int i = 0; i < size; i++) { + memset(&networks->items[i].record, 0xff, sizeof(network_record_t)); + } + + for (int i = 0; i < networks->size; i++) { + network_t *network = &networks->items[i]; + sprintf(plmn, "%s%d", PLMN, i); + plmn_setting = config_setting_get_member(all_plmn_setting, plmn); + if (plmn_setting == NULL) { + printf("PLMN%d not fouund\n", i); + return false; + } + + if ( parse_plmn_param(plmn_setting, &network->conf) == false ) { + return false; + } + gen_network_record_from_conf(&network->conf, &network->record); + network->plmn = network->record.plmn; + } + return true; +} + + diff --git a/openair3/NAS/TOOLS/conf_network.h b/openair3/NAS/TOOLS/conf_network.h new file mode 100644 index 0000000000000000000000000000000000000000..a535841a4cfbc7bc4b41a186ab28dc476a793dbc --- /dev/null +++ b/openair3/NAS/TOOLS/conf_network.h @@ -0,0 +1,54 @@ +#ifndef _CONF_NETWORK_H +#define _CONF_NETWORK_H + +#include <stdbool.h> +#include <libconfig.h> +#include "usim_api.h" + +#define PLMN "PLMN" + +#define FULLNAME "FULLNAME" +#define SHORTNAME "SHORTNAME" +#define MNC "MNC" +#define MCC "MCC" + +#define MIN_TAC 0x0000 +#define MAX_TAC 0xFFFE + +/* + * PLMN network operator record + */ +typedef struct { + unsigned int num; + plmn_t plmn; + char fullname[NET_FORMAT_LONG_SIZE + 1]; + char shortname[NET_FORMAT_SHORT_SIZE + 1]; + tac_t tac_start; + tac_t tac_end; +} network_record_t; + +typedef struct { + const char *fullname; + const char *shortname; + const char *mnc; + const char *mcc; +} plmn_conf_param_t; + +typedef struct { + plmn_conf_param_t conf; + network_record_t record; + plmn_t plmn; +} network_t; + +typedef struct { + int size; + network_t *items; +} networks_t; + +bool parse_plmn_param(config_setting_t *plmn_setting, plmn_conf_param_t *conf); +bool parse_plmns(config_setting_t *all_plmn_setting, networks_t *plmns); + +void gen_network_record_from_conf(const plmn_conf_param_t *conf, network_record_t *record); +int get_plmn_index(const char * mccmnc, const networks_t networks); + +#endif diff --git a/openair3/NAS/TOOLS/conf_parser.c b/openair3/NAS/TOOLS/conf_parser.c new file mode 100644 index 0000000000000000000000000000000000000000..d46142c4614970827c3a050323297480670f848e --- /dev/null +++ b/openair3/NAS/TOOLS/conf_parser.c @@ -0,0 +1,119 @@ +#include "conf_parser.h" + +#include "conf_network.h" +#include "conf_emm.h" +#include "conf_usim.h" +#include "conf_user_data.h" +#include "conf_user_plmn.h" + +bool parse_config_file(const char *output_dir, const char *conf_filename, int output_flags) { + int rc = true; + int ret; + int ue_nb = 0; + config_setting_t *root_setting = NULL; + config_setting_t *ue_setting = NULL; + config_setting_t *all_plmn_setting = NULL; + char user[10]; + config_t cfg; + + networks_t networks;; + + ret = get_config_from_file(conf_filename, &cfg); + if (ret == false) { + exit(1); + } + + root_setting = config_root_setting(&cfg); + ue_nb = config_setting_length(root_setting) - 1; + + all_plmn_setting = config_setting_get_member(root_setting, PLMN); + if (all_plmn_setting == NULL) { + printf("NO PLMN SECTION...EXITING...\n"); + return (false); + } + + if ( parse_plmns(all_plmn_setting, &networks) == false ) { + return false; + } + + for (int i = 0; i < ue_nb; i++) { + emm_nvdata_t emm_data; + + user_nvdata_t user_data; + user_data_conf_t user_data_conf; + + usim_data_t usim_data; + usim_data_conf_t usim_data_conf; + + user_plmns_t user_plmns; + + sprintf(user, "%s%d", UE, i); + + ue_setting = config_setting_get_member(root_setting, user); + if (ue_setting == NULL) { + printf("Check UE%d settings\n", i); + return false; + } + + if ( parse_user_plmns_conf(ue_setting, i, &user_plmns, &usim_data_conf.hplmn, networks) == false ) { + return false; + } + + rc = parse_ue_user_data(ue_setting, i, &user_data_conf); + if (rc != true) { + printf("Problem in USER section for UE%d. EXITING...\n", i); + return false; + } + gen_user_data(&user_data_conf, &user_data); + + rc = parse_ue_sim_param(ue_setting, i, &usim_data_conf); + if (rc != true) { + printf("Problem in SIM section for UE%d. EXITING...\n", i); + return false; + } + gen_usim_data(&usim_data_conf, &usim_data, &user_plmns, networks); + + gen_emm_data(&emm_data, usim_data_conf.hplmn, usim_data_conf.msin, + &user_plmns.equivalents_home, networks); + + if ( output_flags & OUTPUT_UEDATA ) { + write_user_data(output_dir, i, &user_data); + } + + if ( output_flags & OUTPUT_USIM ) { + write_usim_data(output_dir, i, &usim_data); + } + + if ( output_flags & OUTPUT_EMM ) { + write_emm_data(output_dir, i, &emm_data); + } + + user_plmns_free(&user_plmns); + + } + free(networks.items); + networks.size=0; + config_destroy(&cfg); + return(true); +} + +bool get_config_from_file(const char *filename, config_t *config) { + config_init(config); + if (filename == NULL) { + // XXX write error message ? + return(false); + } + + /* Read the file. If there is an error, report it and exit. */ + if (!config_read_file(config, filename)) { + fprintf(stderr, "Cant read config file '%s': %s\n", filename, + config_error_text(config)); + if ( config_error_type(config) == CONFIG_ERR_PARSE ) { + fprintf(stderr, "This is line %d\n", config_error_line(config)); + } + config_destroy(config); + return (false); + } + return true; +} + diff --git a/openair3/NAS/TOOLS/conf_parser.h b/openair3/NAS/TOOLS/conf_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..49d3645faf02a76aa134e5b08ed76c3efbd42bdf --- /dev/null +++ b/openair3/NAS/TOOLS/conf_parser.h @@ -0,0 +1,17 @@ +#ifndef _CONF_PARSER_H +#define _CONF_PARSER_H + +#include <stdbool.h> +#include <libconfig.h> + +#define UE "UE" + +#define OUTPUT_EMM 1 +#define OUTPUT_USIM 2 +#define OUTPUT_UEDATA 4 +#define OUTPUT_ALL 7 + +bool get_config_from_file(const char *filename, config_t *config); +bool parse_config_file(const char *output_dir, const char *filename, int output_flags); + +#endif diff --git a/openair3/NAS/TOOLS/conf_user_data.c b/openair3/NAS/TOOLS/conf_user_data.c new file mode 100644 index 0000000000000000000000000000000000000000..5e14797e166fad8c3ba5a9c5e85ae3ab79ecf2f1 --- /dev/null +++ b/openair3/NAS/TOOLS/conf_user_data.c @@ -0,0 +1,86 @@ +#include <string.h> +#include <stdlib.h> + +#include "commonDef.h" +#include "memory.h" +#include "fs.h" +#include "conf_user_data.h" + +int parse_ue_user_data(config_setting_t *ue_setting, int user_id, user_data_conf_t *u) { + config_setting_t *ue_param_setting = NULL; + + int rc = true; + ue_param_setting = config_setting_get_member(ue_setting, USER); + if (ue_param_setting == NULL) { + printf("Check USER section of UE%d. EXITING...\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, UE_IMEI, &u->imei); + if (rc != 1) { + printf("Check USER IMEI section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, MANUFACTURER, + &u->manufacturer); + if (rc != 1) { + printf("Check USER MANUFACTURER for UE%d FULLNAME. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, MODEL, &u->model); + if (rc != 1) { + printf("Check USER MODEL for UE%d FULLNAME. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, PINCODE, &u->pin); + if (rc != 1) { + printf("Check USER PIN for UE%d FULLNAME. Exiting\n", user_id); + return false; + } + return true; +} + +void gen_user_data(user_data_conf_t *u, user_nvdata_t *user_data) { + memset(user_data, 0, sizeof(user_nvdata_t)); + snprintf(user_data->IMEI, USER_IMEI_SIZE + 1, "%s%d", u->imei, _luhn(u->imei)); + /* + * Manufacturer identifier + */ + strncpy(user_data->manufacturer, u->manufacturer, USER_MANUFACTURER_SIZE); + /* + * Model identifier + */ + strncpy(user_data->model, u->model, USER_MODEL_SIZE); + /* + * SIM Personal Identification Number + */ + strncpy(user_data->PIN, u->pin, USER_PIN_SIZE); +} + +bool write_user_data(const char *directory, int user_id, user_nvdata_t *data) { + int rc; + char* filename = make_filename(directory, USER_NVRAM_FILENAME, user_id); + rc = memory_write(filename, data, sizeof(user_nvdata_t)); + free(filename); + if (rc != RETURNok) { + perror("ERROR\t: memory_write() failed"); + return false; + } + return true; +} + +/* + * Computes the check digit using Luhn algorithm + */ +int _luhn(const char* cc) { + const int m[] = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 }; + int odd = 1, sum = 0; + + for (int i = strlen(cc); i--; odd = !odd) { + int digit = cc[i] - '0'; + sum += odd ? m[digit] : digit; + } + + return 10 - (sum % 10); +} + + diff --git a/openair3/NAS/TOOLS/conf_user_data.h b/openair3/NAS/TOOLS/conf_user_data.h new file mode 100644 index 0000000000000000000000000000000000000000..6b1d641e030c5f4bea3f529ca19531808c504481 --- /dev/null +++ b/openair3/NAS/TOOLS/conf_user_data.h @@ -0,0 +1,27 @@ +#ifndef _CONF_USER_DATA_H +#define _CONF_USER_DATA_H + +#include <stdbool.h> +#include <libconfig.h> +#include "userDef.h" + +#define USER "USER" +#define MANUFACTURER "MANUFACTURER" +#define MODEL "MODEL" +#define UE_IMEI "IMEI" +#define PINCODE "PIN" + +typedef struct { + const char* imei; + const char* manufacturer; + const char* model; + const char* pin; +} user_data_conf_t; + +void gen_user_data(user_data_conf_t *u, user_nvdata_t *user_data); +bool write_user_data(const char *directory, int user_id, user_nvdata_t *data); +int parse_ue_user_data(config_setting_t *ue_setting, int user_id, user_data_conf_t *u); + +int _luhn(const char* cc); + +#endif diff --git a/openair3/NAS/TOOLS/conf_user_plmn.c b/openair3/NAS/TOOLS/conf_user_plmn.c new file mode 100644 index 0000000000000000000000000000000000000000..3b3c6dd3e6c1f2759d06e39274d711de512f0e96 --- /dev/null +++ b/openair3/NAS/TOOLS/conf_user_plmn.c @@ -0,0 +1,81 @@ +#include <stdlib.h> +#include <string.h> +#include "conf_user_plmn.h" + +bool parse_user_plmns_conf(config_setting_t *ue_setting, int user_id, + user_plmns_t *user_plmns, const char **h, + const networks_t networks) { + int nb_errors = 0; + const char *hplmn; + + if ( config_setting_lookup_string(ue_setting, HPLMN, h) != 1 ) { + printf("Check HPLMN section for UE%d. Exiting\n", user_id); + return false; + } + hplmn = *h; + if (get_plmn_index(hplmn, networks) == -1) { + printf("HPLMN for UE%d is not defined in PLMN section. Exiting\n", + user_id); + return false; + } + + if ( parse_Xplmn(ue_setting, UCPLMN, user_id, &user_plmns->users_controlled, networks) == false ) + nb_errors++; + if ( parse_Xplmn(ue_setting, OPLMN, user_id, &user_plmns->operators, networks) == false ) + nb_errors++; + if ( parse_Xplmn(ue_setting, OCPLMN, user_id, &user_plmns->operators_controlled, networks) == false ) + nb_errors++; + if ( parse_Xplmn(ue_setting, FPLMN, user_id, &user_plmns->forbiddens, networks) == false ) + nb_errors++; + if ( parse_Xplmn(ue_setting, EHPLMN, user_id, &user_plmns->equivalents_home, networks) == false ) + nb_errors++; + + if ( nb_errors > 0 ) + return false; + return true; +} + +bool parse_Xplmn(config_setting_t *ue_setting, const char *section, + int user_id, plmns_list *plmns, const networks_t networks) { + int rc; + int item_count; + config_setting_t *setting; + + setting = config_setting_get_member(ue_setting, section); + if (setting == NULL) { + printf("Check %s section for UE%d. Exiting\n", section, user_id); + return false; + } + + item_count = config_setting_length(setting); + int *datas = malloc(item_count * sizeof(int)); + for (int i = 0; i < item_count; i++) { + const char *mccmnc = config_setting_get_string_elem(setting, i); + if (mccmnc == NULL) { + printf("Check %s section for UE%d. Exiting\n", section, user_id); + free(datas); + return false; + } + rc = get_plmn_index(mccmnc, networks); + if (rc == -1) { + printf("The PLMN %s is not defined in PLMN section. Exiting...\n", + mccmnc); + free(datas); + return false; + } + datas[i] = rc; + } + + plmns->size = item_count; + plmns->items = datas; + return true; +} + +void user_plmns_free(user_plmns_t *user_plmns) { + free(user_plmns->users_controlled.items); + free(user_plmns->operators.items); + free(user_plmns->operators_controlled.items); + free(user_plmns->forbiddens.items); + free(user_plmns->equivalents_home.items); + memset(user_plmns, 0, sizeof(user_plmns_t)); +} diff --git a/openair3/NAS/TOOLS/conf_user_plmn.h b/openair3/NAS/TOOLS/conf_user_plmn.h new file mode 100644 index 0000000000000000000000000000000000000000..561767b6c4823471171e1bd5e628707d88581b23 --- /dev/null +++ b/openair3/NAS/TOOLS/conf_user_plmn.h @@ -0,0 +1,37 @@ +#ifndef _CONF_USER_H +#define _CONF_USER_H + +#include <stdbool.h> +#include <libconfig.h> +#include "conf_network.h" + +#define HPLMN "HPLMN" +#define UCPLMN "UCPLMN_LIST" +#define OPLMN "OPLMN_LIST" +#define OCPLMN "OCPLMN_LIST" +#define FPLMN "FPLMN_LIST" +#define EHPLMN "EHPLMN_LIST" + +typedef struct { + int size; + int *items; +} plmns_list; + +typedef struct { + plmns_list users_controlled; + plmns_list operators; + plmns_list operators_controlled; + plmns_list forbiddens; + plmns_list equivalents_home; +} user_plmns_t; + +bool parse_user_plmns_conf(config_setting_t *ue_setting, int user_id, + user_plmns_t *user_plmns, const char **h, + const networks_t networks); + +bool parse_Xplmn(config_setting_t *ue_setting, const char *section, + int user_id, plmns_list *plmns, const networks_t networks); + +void user_plmns_free(user_plmns_t *user_plmns); + +#endif diff --git a/openair3/NAS/TOOLS/conf_usim.c b/openair3/NAS/TOOLS/conf_usim.c new file mode 100644 index 0000000000000000000000000000000000000000..3a5c6dbf6d146285fd0e3dedc37b5b8bf6d07ecf --- /dev/null +++ b/openair3/NAS/TOOLS/conf_usim.c @@ -0,0 +1,308 @@ +#include <string.h> +#include <stdlib.h> + +#include "userDef.h" +#include "utils.h" +#include "conf_emm.h" +#include "fs.h" +#include "conf_usim.h" + +bool parse_ue_sim_param(config_setting_t *ue_setting, int user_id, usim_data_conf_t *u) { + int rc = true; + config_setting_t *ue_param_setting = NULL; + ue_param_setting = config_setting_get_member(ue_setting, SIM); + if (ue_param_setting == NULL) { + printf("Check SIM section for UE%d. EXITING...\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, MSIN, &u->msin); + if (rc != 1 || strlen(u->msin) > 10 || strlen(u->msin) < 9) { + printf("Check SIM MSIN section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, USIM_API_K, + &u->usim_api_k); + if (rc != 1) { + printf("Check SIM USIM_API_K section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, OPC, &u->opc); + if (rc != 1) { + printf("Check SIM OPC section for UE%d. Exiting\n", user_id); + return false; + } + rc = config_setting_lookup_string(ue_param_setting, MSISDN, &u->msisdn); + if (rc != 1) { + printf("Check SIM MSISDN section for UE%d. Exiting\n", user_id); + return false; + } + return true; +} + +void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data, + const user_plmns_t *user_plmns, const networks_t networks) { + int hplmn_index = get_plmn_index(u->hplmn, networks); + const plmn_conf_param_t *conf = &networks.items[hplmn_index].conf; + memset(usim_data, 0, sizeof(usim_data_t)); + usim_data->imsi.length = 8; + usim_data->imsi.u.num.parity = get_msin_parity(u->msin, + conf->mcc, + conf->mnc); + + usim_data->imsi.u.num.digit1 = conf->mcc[0]; + usim_data->imsi.u.num.digit2 = conf->mcc[1]; + usim_data->imsi.u.num.digit3 = conf->mcc[2]; + + usim_data->imsi.u.num.digit4 = conf->mnc[0]; + usim_data->imsi.u.num.digit5 = conf->mnc[1]; + + if (strlen(conf->mnc) == 2) { + usim_data->imsi.u.num.digit6 = u->msin[0]; + usim_data->imsi.u.num.digit7 = u->msin[1]; + usim_data->imsi.u.num.digit8 = u->msin[2]; + usim_data->imsi.u.num.digit9 = u->msin[3]; + usim_data->imsi.u.num.digit10 = u->msin[4]; + usim_data->imsi.u.num.digit11 = u->msin[5]; + usim_data->imsi.u.num.digit12 = u->msin[6]; + usim_data->imsi.u.num.digit13 = u->msin[7]; + usim_data->imsi.u.num.digit14 = u->msin[8]; + usim_data->imsi.u.num.digit15 = u->msin[9]; + } else { + usim_data->imsi.u.num.digit6 = conf->mnc[2]; + usim_data->imsi.u.num.digit7 = u->msin[0]; + usim_data->imsi.u.num.digit8 = u->msin[1]; + usim_data->imsi.u.num.digit9 = u->msin[2]; + usim_data->imsi.u.num.digit10 = u->msin[3]; + usim_data->imsi.u.num.digit11 = u->msin[4]; + usim_data->imsi.u.num.digit12 = u->msin[5]; + usim_data->imsi.u.num.digit13 = u->msin[6]; + usim_data->imsi.u.num.digit14 = u->msin[7]; + usim_data->imsi.u.num.digit15 = u->msin[8]; + } + + /* + * Ciphering and Integrity Keys + */ + usim_data->keys.ksi = KSI; + memset(&usim_data->keys.ck, 0, USIM_CK_SIZE); + memset(&usim_data->keys.ik, 0, USIM_IK_SIZE); + /* + * Higher Priority PLMN search period + */ + usim_data->hpplmn = 0x00; /* Disable timer */ + + /* + * List of Forbidden PLMNs + */ + for (int i = 0; i < USIM_FPLMN_MAX; i++) { + memset(&usim_data->fplmn[i], 0xff, sizeof(plmn_t)); + } + if (user_plmns->forbiddens.size > 0) { + for (int i = 0; i < user_plmns->forbiddens.size; i++) { + usim_data->fplmn[i] = networks.items[user_plmns->forbiddens.items[i]].plmn; + } + } + + /* + * Location Information + */ + usim_data->loci.tmsi = DEFAULT_TMSI; + usim_data->loci.lai.plmn = networks.items[hplmn_index].plmn; + usim_data->loci.lai.lac = DEFAULT_LAC; + usim_data->loci.status = USIM_LOCI_NOT_UPDATED; + /* + * Packet Switched Location Information + */ + usim_data->psloci.p_tmsi = DEFAULT_P_TMSI; + usim_data->psloci.signature[0] = 0x01; + usim_data->psloci.signature[1] = 0x02; + usim_data->psloci.signature[2] = 0x03; + usim_data->psloci.rai.plmn = networks.items[hplmn_index].plmn; + usim_data->psloci.rai.lac = DEFAULT_LAC; + usim_data->psloci.rai.rac = DEFAULT_RAC; + usim_data->psloci.status = USIM_PSLOCI_NOT_UPDATED; + /* + * Administrative Data + */ + usim_data->ad.UE_Operation_Mode = USIM_NORMAL_MODE; + usim_data->ad.Additional_Info = 0xffff; + usim_data->ad.MNC_Length = strlen(conf->mnc); + /* + * EPS NAS security context + */ + usim_data->securityctx.length = 52; + usim_data->securityctx.KSIasme.type = USIM_KSI_ASME_TAG; + usim_data->securityctx.KSIasme.length = 1; + usim_data->securityctx.KSIasme.value[0] = KSI_ASME; + usim_data->securityctx.Kasme.type = USIM_K_ASME_TAG; + usim_data->securityctx.Kasme.length = USIM_K_ASME_SIZE; + memset(usim_data->securityctx.Kasme.value, 0, + usim_data->securityctx.Kasme.length); + usim_data->securityctx.ulNAScount.type = USIM_UL_NAS_COUNT_TAG; + usim_data->securityctx.ulNAScount.length = USIM_UL_NAS_COUNT_SIZE; + memset(usim_data->securityctx.ulNAScount.value, 0, + usim_data->securityctx.ulNAScount.length); + usim_data->securityctx.dlNAScount.type = USIM_DL_NAS_COUNT_TAG; + usim_data->securityctx.dlNAScount.length = USIM_DL_NAS_COUNT_SIZE; + memset(usim_data->securityctx.dlNAScount.value, 0, + usim_data->securityctx.dlNAScount.length); + usim_data->securityctx.algorithmID.type = USIM_INT_ENC_ALGORITHMS_TAG; + usim_data->securityctx.algorithmID.length = 1; + usim_data->securityctx.algorithmID.value[0] = SECURITY_ALGORITHMS; + /* + * Subcriber's Number + */ + usim_data->msisdn.length = 7; + usim_data->msisdn.number.ext = 1; + usim_data->msisdn.number.ton = MSISDN_TON_UNKNOWKN; + usim_data->msisdn.number.npi = MSISDN_NPI_ISDN_TELEPHONY; + usim_data->msisdn.conf1_record_id = 0xff; /* Not used */ + usim_data->msisdn.ext1_record_id = 0xff; /* Not used */ + int j = 0; + for (int i = 0; i < strlen(u->msisdn); i += 2) { + usim_data->msisdn.number.digit[j].msb = u->msisdn[i]; + j++; + } + j = 0; + for (int i = 1; i < strlen(u->msisdn); i += 2) { + usim_data->msisdn.number.digit[j].lsb = u->msisdn[i]; + j++; + + } + if (strlen(u->msisdn) % 2 == 0) { + for (int i = strlen(u->msisdn) / 2; i < 10; i++) { + usim_data->msisdn.number.digit[i].msb = 0xf; + usim_data->msisdn.number.digit[i].lsb = 0xf; + } + } else { + usim_data->msisdn.number.digit[strlen(u->msisdn) / 2].lsb = 0xf; + for (int i = (strlen(u->msisdn) / 2) + 1; i < 10; i++) { + usim_data->msisdn.number.digit[i].msb = 0xf; + usim_data->msisdn.number.digit[i].lsb = 0xf; + } + } + /* + * PLMN Network Name and Operator PLMN List + */ + for (int i = 0; i < user_plmns->operators.size; i++) { + network_record_t record = networks.items[user_plmns->operators.items[i]].record; + usim_data->pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG; + usim_data->pnn[i].fullname.length = strlen(record.fullname); + strncpy((char*) usim_data->pnn[i].fullname.value, record.fullname, + usim_data->pnn[i].fullname.length); + usim_data->pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG; + usim_data->pnn[i].shortname.length = strlen(record.shortname); + strncpy((char*) usim_data->pnn[i].shortname.value, record.shortname, + usim_data->pnn[i].shortname.length); + usim_data->opl[i].plmn = record.plmn; + usim_data->opl[i].start = record.tac_start; + usim_data->opl[i].end = record.tac_end; + usim_data->opl[i].record_id = i; + } + if (user_plmns->operators.size < USIM_OPL_MAX) { + for (int i = user_plmns->operators.size; i < USIM_OPL_MAX; i++) { + memset(&usim_data->opl[i].plmn, 0xff, sizeof(plmn_t)); + } + } + + /* + * List of Equivalent HPLMNs + */ + for (int i = 0; i < user_plmns->equivalents_home.size; i++) { + usim_data->ehplmn[i] = networks.items[user_plmns->equivalents_home.items[i]].plmn; + } + if (user_plmns->equivalents_home.size < USIM_EHPLMN_MAX) { + for (int i = user_plmns->equivalents_home.size; i < USIM_EHPLMN_MAX; i++) { + memset(&usim_data->ehplmn[i], 0xff, sizeof(plmn_t)); + } + } + /* + * Home PLMN Selector with Access Technology + */ + usim_data->hplmn.plmn = networks.items[hplmn_index].plmn; + usim_data->hplmn.AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); + + /* + * List of user controlled PLMN selector with Access Technology + */ + for (int i = 0; i < USIM_PLMN_MAX; i++) { + memset(&usim_data->plmn[i], 0xff, sizeof(plmn_t)); + } + if (user_plmns->users_controlled.size > 0) { + for (int i = 0; i < user_plmns->users_controlled.size; i++) { + usim_data->plmn[i].plmn = networks.items[user_plmns->users_controlled.items[i]].plmn; + } + } + + // List of operator controlled PLMN selector with Access Technology + + for (int i = 0; i < USIM_OPLMN_MAX; i++) { + memset(&usim_data->oplmn[i], 0xff, sizeof(plmn_t)); + } + if (user_plmns->operators_controlled.size > 0) { + for (int i = 0; i < user_plmns->operators_controlled.size; i++) { + usim_data->oplmn[i].plmn = networks.items[user_plmns->operators_controlled.items[i]].plmn; + usim_data->oplmn[i].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN + | USIM_ACT_EUTRAN); + } + } + /* + * EPS Location Information + */ + usim_data->epsloci.guti.gummei.plmn = + networks.items[hplmn_index].plmn; + usim_data->epsloci.guti.gummei.MMEgid = DEFAULT_MME_ID; + usim_data->epsloci.guti.gummei.MMEcode = DEFAULT_MME_CODE; + usim_data->epsloci.guti.m_tmsi = DEFAULT_M_TMSI; + usim_data->epsloci.tai.plmn = usim_data->epsloci.guti.gummei.plmn; + usim_data->epsloci.tai.tac = DEFAULT_TAC; + usim_data->epsloci.status = USIM_EPSLOCI_UPDATED; + /* + * Non-Access Stratum configuration + */ + usim_data->nasconfig.NAS_SignallingPriority.type = + USIM_NAS_SIGNALLING_PRIORITY_TAG; + usim_data->nasconfig.NAS_SignallingPriority.length = 1; + usim_data->nasconfig.NAS_SignallingPriority.value[0] = 0x00; + usim_data->nasconfig.NMO_I_Behaviour.type = USIM_NMO_I_BEHAVIOUR_TAG; + usim_data->nasconfig.NMO_I_Behaviour.length = 1; + usim_data->nasconfig.NMO_I_Behaviour.value[0] = 0x00; + usim_data->nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG; + usim_data->nasconfig.AttachWithImsi.length = 1; +#if defined(START_WITH_GUTI) + usim_data->nasconfig.AttachWithImsi.value[0] = 0x00; +#else + usim_data->nasconfig.AttachWithImsi.value[0] = 0x01; +#endif + usim_data->nasconfig.MinimumPeriodicSearchTimer.type = + USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG; + usim_data->nasconfig.MinimumPeriodicSearchTimer.length = 1; + usim_data->nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00; + usim_data->nasconfig.ExtendedAccessBarring.type = + USIM_EXTENDED_ACCESS_BARRING_TAG; + usim_data->nasconfig.ExtendedAccessBarring.length = 1; + usim_data->nasconfig.ExtendedAccessBarring.value[0] = 0x00; + usim_data->nasconfig.Timer_T3245_Behaviour.type = + USIM_TIMER_T3245_BEHAVIOUR_TAG; + usim_data->nasconfig.Timer_T3245_Behaviour.length = 1; + usim_data->nasconfig.Timer_T3245_Behaviour.value[0] = 0x00; + + /* initialize the subscriber authentication security key */ + if (hex_string_to_hex_value(usim_data->keys.usim_api_k, + u->usim_api_k, USIM_API_K_SIZE) == -1 || + hex_string_to_hex_value(usim_data->keys.opc, + u->opc, OPC_SIZE) == -1) { + fprintf(stderr, "fix your configuration file\n"); + exit(1); + } +} + +bool write_usim_data(const char *directory, int user_id, usim_data_t *usim_data){ + int rc; + char *filename = make_filename(directory, USIM_API_NVRAM_FILENAME, user_id); + rc = usim_api_write(filename, usim_data); + free(filename); + return rc; +} + + diff --git a/openair3/NAS/TOOLS/conf_usim.h b/openair3/NAS/TOOLS/conf_usim.h new file mode 100644 index 0000000000000000000000000000000000000000..4768a6d8c0c9239a639fa82b5946ca013d0ad98b --- /dev/null +++ b/openair3/NAS/TOOLS/conf_usim.h @@ -0,0 +1,48 @@ +#ifndef _CONF_USIM_H +#define _CONF_USIM_H + +#include <libconfig.h> +#include "usim_api.h" +#include "conf_user_plmn.h" + +#define SIM "SIM" +#define MSIN "MSIN" +#define USIM_API_K "USIM_API_K" +#define OPC "OPC" +#define MSISDN "MSISDN" + +#define KSI USIM_KSI_NOT_AVAILABLE +#define KSI_ASME USIM_KSI_NOT_AVAILABLE + +#define OPC_SIZE 16 + +#define DEFAULT_TMSI 0x0000000D +#define DEFAULT_P_TMSI 0x0000000D +#define DEFAULT_M_TMSI 0x0000000D + +#define DEFAULT_RAC 0x01 +#define DEFAULT_TAC 0x0001 +#define DEFAULT_LAC 0xFFFE + +#define DEFAULT_MME_ID 0x0102 +#define DEFAULT_MME_CODE 0x0F + +// TODO add this setting in configuration file +#define INT_ALGO USIM_INT_EIA2 +#define ENC_ALGO USIM_ENC_EEA0 +#define SECURITY_ALGORITHMS (ENC_ALGO | INT_ALGO) + +typedef struct { + const char *msin; + const char *usim_api_k; + const char *msisdn; + const char *opc; + const char *hplmn; +} usim_data_conf_t; + +bool parse_ue_sim_param(config_setting_t *ue_setting, int user_id, usim_data_conf_t *u); +bool write_usim_data(const char *directory, int user_id, usim_data_t *usim_data); +void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data, + const user_plmns_t *user_plmns, const networks_t networks); + +#endif diff --git a/openair3/NAS/TOOLS/display.c b/openair3/NAS/TOOLS/display.c new file mode 100644 index 0000000000000000000000000000000000000000..363fae76b8eed58ee56e959058a03a3df705403a --- /dev/null +++ b/openair3/NAS/TOOLS/display.c @@ -0,0 +1,380 @@ +#include <stdlib.h> +#include <string.h> + +#include "userDef.h" +#include "usim_api.h" +#include "emmData.h" +#include "display.h" +#include "memory.h" +#include "fs.h" + +#define PRINT_PLMN_DIGIT(d) if ((d) != 0xf) printf("%u", (d)) + +#define PRINT_PLMN(plmn) \ + PRINT_PLMN_DIGIT((plmn).MCCdigit1); \ + PRINT_PLMN_DIGIT((plmn).MCCdigit2); \ + PRINT_PLMN_DIGIT((plmn).MCCdigit3); \ + PRINT_PLMN_DIGIT((plmn).MNCdigit1); \ + PRINT_PLMN_DIGIT((plmn).MNCdigit2); \ + PRINT_PLMN_DIGIT((plmn).MNCdigit3) + +#define PRINT_PLMN_DIGIT(d) if ((d) != 0xf) printf("%u", (d)) + +#define PRINT_PLMN(plmn) \ + PRINT_PLMN_DIGIT((plmn).MCCdigit1); \ + PRINT_PLMN_DIGIT((plmn).MCCdigit2); \ + PRINT_PLMN_DIGIT((plmn).MCCdigit3); \ + PRINT_PLMN_DIGIT((plmn).MNCdigit1); \ + PRINT_PLMN_DIGIT((plmn).MNCdigit2); \ + PRINT_PLMN_DIGIT((plmn).MNCdigit3) + +// return number of files displayed +int display_data_from_directory(const char *directory, int flags) { + int user_id = 0; + char *filename; + bool found = true; + int displayed_count = 0; + + while ( found ) { + found = false; + + if ( flags & DISPLAY_UEDATA ) { + filename = get_ue_filename(directory, user_id); + if ( file_exist_and_is_readable(filename) ) { + display_ue_data(filename); + displayed_count += 1; + found = true; + printf("UE identity data file: %s\n", filename); + } + free(filename); + } + + if ( flags & DISPLAY_EMM ) { + filename = get_emm_filename(directory, user_id); + if ( file_exist_and_is_readable(filename) ) { + display_emm_data(filename); + displayed_count += 1; + found = true; + printf("EPS Mobility Management data file: %s\n", filename); + } + free(filename); + } + + if ( flags & DISPLAY_USIM ) { + filename = get_usim_filename(directory, user_id); + if ( file_exist_and_is_readable(filename) ) { + display_usim_data(filename); + displayed_count += 1; + found = true; + printf("USIM data file: %s\n", filename); + } + free(filename); + } + + user_id += 1; + } + return displayed_count; +} + +void display_ue_data(const char *filename) { + user_nvdata_t data; + int rc; + /* + * Read UE's non-volatile data + */ + memset(&data, 0, sizeof(user_nvdata_t)); + rc = memory_read(filename, &data, sizeof(user_nvdata_t)); + + if (rc != RETURNok) { + perror("ERROR\t: memory_read() failed"); + exit(false); + } + + /* + * Display UE's non-volatile data + */ + printf("\nUE's non-volatile data:\n\n"); + printf("IMEI\t\t= %s\n", data.IMEI); + printf("manufacturer\t= %s\n", data.manufacturer); + printf("model\t\t= %s\n", data.model); + printf("PIN\t\t= %s\n", data.PIN); +} + +/* + * Displays UE's non-volatile EMM data + */ +void display_emm_data(const char *filename) { + + int rc; + emm_nvdata_t data; + + /* + * Read EMM non-volatile data + */ + memset(&data, 0, sizeof(emm_nvdata_t)); + rc = memory_read(filename, &data, sizeof(emm_nvdata_t)); + if (rc != RETURNok) { + perror("ERROR\t: memory_read() failed "); + exit(false); + } + + /* + * Display EMM non-volatile data + */ + printf("\nEMM non-volatile data:\n\n"); + + printf("IMSI\t\t= "); + + if (data.imsi.u.num.digit6 == 0b1111) { + if (data.imsi.u.num.digit15 == 0b1111) { + printf("%u%u%u.%u%u.%u%u%u%u%u%u%u%u\n", data.imsi.u.num.digit1, + data.imsi.u.num.digit2, data.imsi.u.num.digit3, + data.imsi.u.num.digit4, data.imsi.u.num.digit5, + + data.imsi.u.num.digit7, data.imsi.u.num.digit8, + data.imsi.u.num.digit9, data.imsi.u.num.digit10, + data.imsi.u.num.digit11, data.imsi.u.num.digit12, + data.imsi.u.num.digit13, data.imsi.u.num.digit14); + } else { + printf("%u%u%u.%u%u.%u%u%u%u%u%u%u%u%u\n", data.imsi.u.num.digit1, + data.imsi.u.num.digit2, data.imsi.u.num.digit3, + data.imsi.u.num.digit4, data.imsi.u.num.digit5, + + data.imsi.u.num.digit7, data.imsi.u.num.digit8, + data.imsi.u.num.digit9, data.imsi.u.num.digit10, + data.imsi.u.num.digit11, data.imsi.u.num.digit12, + data.imsi.u.num.digit13, data.imsi.u.num.digit14, + data.imsi.u.num.digit15); + } + } else { + if (data.imsi.u.num.digit15 == 0b1111) { + printf("%u%u%u.%u%u%u.%u%u%u%u%u%u%u%u\n", data.imsi.u.num.digit1, + data.imsi.u.num.digit2, data.imsi.u.num.digit3, + data.imsi.u.num.digit4, data.imsi.u.num.digit5, + data.imsi.u.num.digit6, + + data.imsi.u.num.digit7, data.imsi.u.num.digit8, + data.imsi.u.num.digit9, data.imsi.u.num.digit10, + data.imsi.u.num.digit11, data.imsi.u.num.digit12, + data.imsi.u.num.digit13, data.imsi.u.num.digit14); + } else { + printf("%u%u%u.%u%u%u.%u%u%u%u%u%u%u%u%u\n", data.imsi.u.num.digit1, + data.imsi.u.num.digit2, data.imsi.u.num.digit3, + data.imsi.u.num.digit4, data.imsi.u.num.digit5, + data.imsi.u.num.digit6, + + data.imsi.u.num.digit7, data.imsi.u.num.digit8, + data.imsi.u.num.digit9, data.imsi.u.num.digit10, + data.imsi.u.num.digit11, data.imsi.u.num.digit12, + data.imsi.u.num.digit13, data.imsi.u.num.digit14, + data.imsi.u.num.digit15); + } + } + + printf("RPLMN\t\t= "); + PRINT_PLMN(data.rplmn); + printf("\n"); + + for (int i = 0; i < data.eplmn.n_plmns; i++) { + printf("EPLMN[%d]\t= ", i); + PRINT_PLMN(data.eplmn.plmn[i]); + printf("\n"); + } +} + +void display_usim_data(const char *filename) { + + int rc; + usim_data_t data = { }; + + rc = usim_api_read(filename, &data); + + if (rc != RETURNok) { + perror("ERROR\t: usim_api_read() failed"); + exit(2); + } + + /* + * Display USIM application data + */ + printf("\nUSIM data:\n\n"); + int digits; + + printf("Administrative Data:\n"); + printf("\tUE_Operation_Mode\t= 0x%.2x\n", data.ad.UE_Operation_Mode); + printf("\tAdditional_Info\t\t= 0x%.4x\n", data.ad.Additional_Info); + printf("\tMNC_Length\t\t= %d\n\n", data.ad.MNC_Length); + + printf("IMSI:\n"); + printf("\tlength\t= %d\n", data.imsi.length); + printf("\tparity\t= %s\n", + data.imsi.u.num.parity == EVEN_PARITY ? "Even" : "Odd"); + digits = (data.imsi.length * 2) - 1 + - (data.imsi.u.num.parity == EVEN_PARITY ? 1 : 0); + printf("\tdigits\t= %d\n", digits); + printf("\tdigits\t= %u%u%u%u%u%x%u%u%u%u", + data.imsi.u.num.digit1, // MCC digit 1 + data.imsi.u.num.digit2, // MCC digit 2 + data.imsi.u.num.digit3, // MCC digit 3 + data.imsi.u.num.digit4, // MNC digit 1 + data.imsi.u.num.digit5, // MNC digit 2 + data.imsi.u.num.digit6, // MNC digit 3 + data.imsi.u.num.digit7, data.imsi.u.num.digit8, + data.imsi.u.num.digit9, data.imsi.u.num.digit10); + + if (digits >= 11) + printf("%x", data.imsi.u.num.digit11); + + if (digits >= 12) + printf("%x", data.imsi.u.num.digit12); + + if (digits >= 13) + printf("%x", data.imsi.u.num.digit13); + + if (digits >= 14) + printf("%x", data.imsi.u.num.digit14); + + if (digits >= 15) + printf("%x", data.imsi.u.num.digit15); + + printf("\n\n"); + + printf("Ciphering and Integrity Keys:\n"); + printf("\tKSI\t: 0x%.2x\n", data.keys.ksi); + char key[USIM_CK_SIZE + 1]; + key[USIM_CK_SIZE] = '\0'; + memcpy(key, data.keys.ck, USIM_CK_SIZE); + printf("\tCK\t: \"%s\"\n", key); + memcpy(key, data.keys.ik, USIM_IK_SIZE); + printf("\tIK\t: \"%s\"\n", key); + + printf("\n\tusim_api_k:"); + for (int i = 0; i < 16; i++) + printf(" %2.2x", data.keys.usim_api_k[i]); + printf("\n\topc :"); + for (int i = 0; i < 16; i++) + printf(" %2.2x", data.keys.opc[i]); + printf("\n\n"); + + printf("EPS NAS security context:\n"); + printf("\tKSIasme\t: 0x%.2x\n", data.securityctx.KSIasme.value[0]); + char kasme[USIM_K_ASME_SIZE + 1]; + kasme[USIM_K_ASME_SIZE] = '\0'; + memcpy(kasme, data.securityctx.Kasme.value, USIM_K_ASME_SIZE); + printf("\tKasme\t: \"%s\"\n", kasme); + printf("\tulNAScount\t: 0x%.8x\n", + *(uint32_t*) data.securityctx.ulNAScount.value); + printf("\tdlNAScount\t: 0x%.8x\n", + *(uint32_t*) data.securityctx.dlNAScount.value); + printf("\talgorithmID\t: 0x%.2x\n\n", + data.securityctx.algorithmID.value[0]); + + printf("MSISDN\t= %u%u%u %u%u%u%u %u%u%u%u\n\n", + data.msisdn.number.digit[0].msb, data.msisdn.number.digit[0].lsb, + data.msisdn.number.digit[1].msb, data.msisdn.number.digit[1].lsb, + data.msisdn.number.digit[2].msb, data.msisdn.number.digit[2].lsb, + data.msisdn.number.digit[3].msb, data.msisdn.number.digit[3].lsb, + data.msisdn.number.digit[4].msb, data.msisdn.number.digit[4].lsb, + data.msisdn.number.digit[5].msb); + + for (int i = 0; i < USIM_PNN_MAX; i++) { + printf("PNN[%d]\t= {%s, %s}\n", i, data.pnn[i].fullname.value, + data.pnn[i].shortname.value); + } + + printf("\n"); + + for (int i = 0; i < USIM_OPL_MAX; i++) { + printf("OPL[%d]\t= ", i); + PRINT_PLMN(data.opl[i].plmn); + printf(", TAC = [%.4x - %.4x], record_id = %d\n", data.opl[i].start, + data.opl[i].end, data.opl[i].record_id); + } + + printf("\n"); + + printf("HPLMN\t\t= "); + PRINT_PLMN(data.hplmn.plmn); + printf(", AcT = 0x%x\n\n", data.hplmn.AcT); + + for (int i = 0; i < USIM_FPLMN_MAX; i++) { + printf("FPLMN[%d]\t= ", i); + PRINT_PLMN(data.fplmn[i]); + printf("\n"); + } + + printf("\n"); + + for (int i = 0; i < USIM_EHPLMN_MAX; i++) { + printf("EHPLMN[%d]\t= ", i); + PRINT_PLMN(data.ehplmn[i]); + printf("\n"); + } + + printf("\n"); + + for (int i = 0; i < USIM_PLMN_MAX; i++) { + printf("PLMN[%d]\t\t= ", i); + PRINT_PLMN(data.plmn[i].plmn); + printf(", AcTPLMN = 0x%x", data.plmn[i].AcT); + printf("\n"); + } + + printf("\n"); + + for (int i = 0; i < USIM_OPLMN_MAX; i++) { + printf("OPLMN[%d]\t= ", i); + PRINT_PLMN(data.oplmn[i].plmn); + printf(", AcTPLMN = 0x%x", data.oplmn[i].AcT); + printf("\n"); + } + + printf("\n"); + + printf("HPPLMN\t\t= 0x%.2x (%d minutes)\n\n", data.hpplmn, data.hpplmn); + + printf("LOCI:\n"); + printf("\tTMSI = 0x%.4x\n", data.loci.tmsi); + printf("\tLAI\t: PLMN = "); + PRINT_PLMN(data.loci.lai.plmn); + printf(", LAC = 0x%.2x\n", data.loci.lai.lac); + printf("\tstatus\t= %d\n\n", data.loci.status); + + printf("PSLOCI:\n"); + printf("\tP-TMSI = 0x%.4x\n", data.psloci.p_tmsi); + printf("\tsignature = 0x%x 0x%x 0x%x\n", data.psloci.signature[0], + data.psloci.signature[1], data.psloci.signature[2]); + printf("\tRAI\t: PLMN = "); + PRINT_PLMN(data.psloci.rai.plmn); + printf(", LAC = 0x%.2x, RAC = 0x%.1x\n", data.psloci.rai.lac, + data.psloci.rai.rac); + printf("\tstatus\t= %d\n\n", data.psloci.status); + + printf("EPSLOCI:\n"); + printf("\tGUTI\t: GUMMEI\t: (PLMN = "); + PRINT_PLMN(data.epsloci.guti.gummei.plmn); + printf(", MMEgid = 0x%.2x, MMEcode = 0x%.1x)", + data.epsloci.guti.gummei.MMEgid, data.epsloci.guti.gummei.MMEcode); + printf(", M-TMSI = 0x%.4x\n", data.epsloci.guti.m_tmsi); + printf("\tTAI\t: PLMN = "); + PRINT_PLMN(data.epsloci.tai.plmn); + printf(", TAC = 0x%.2x\n", data.epsloci.tai.tac); + printf("\tstatus\t= %d\n\n", data.epsloci.status); + + printf("NASCONFIG:\n"); + printf("\tNAS_SignallingPriority\t\t: 0x%.2x\n", + data.nasconfig.NAS_SignallingPriority.value[0]); + printf("\tNMO_I_Behaviour\t\t\t: 0x%.2x\n", + data.nasconfig.NMO_I_Behaviour.value[0]); + printf("\tAttachWithImsi\t\t\t: 0x%.2x\n", + data.nasconfig.AttachWithImsi.value[0]); + printf("\tMinimumPeriodicSearchTimer\t: 0x%.2x\n", + data.nasconfig.MinimumPeriodicSearchTimer.value[0]); + printf("\tExtendedAccessBarring\t\t: 0x%.2x\n", + data.nasconfig.ExtendedAccessBarring.value[0]); + printf("\tTimer_T3245_Behaviour\t\t: 0x%.2x\n", + data.nasconfig.Timer_T3245_Behaviour.value[0]); + +} + + diff --git a/openair3/NAS/TOOLS/display.h b/openair3/NAS/TOOLS/display.h new file mode 100644 index 0000000000000000000000000000000000000000..fef721c490b8cf82b70416d493e86340f7d16d3e --- /dev/null +++ b/openair3/NAS/TOOLS/display.h @@ -0,0 +1,16 @@ +#ifndef _DISPLAY_H +#define _DISPLAY_H + +#define DISPLAY_EMM 1 +#define DISPLAY_USIM 2 +#define DISPLAY_UEDATA 4 +#define DISPLAY_ALL 7 + +// return number of files displayed +int display_data_from_directory(const char *directory, int flags); + +void display_ue_data(const char *filename); +void display_emm_data(const char *filename); +void display_usim_data(const char *filename); + +#endif diff --git a/openair3/NAS/TOOLS/fs.c b/openair3/NAS/TOOLS/fs.c new file mode 100644 index 0000000000000000000000000000000000000000..c25f10a1e790d8c9d34051e32831781948ebf77f --- /dev/null +++ b/openair3/NAS/TOOLS/fs.c @@ -0,0 +1,52 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "fs.h" +#include "user_api.h" +#include "utils.h" + +bool file_exist_and_is_readable(const char *filename) { + FILE *file ; + file = fopen(filename, "r"); + if ( file == NULL ) + return false; + fclose(file); + return true; +} + +char *get_ue_filename(const char *output_dir, int user_id) { + return make_filename(output_dir, USER_NVRAM_FILENAME, user_id); +} + +char *get_emm_filename(const char *output_dir, int user_id) { + return make_filename(output_dir, EMM_NVRAM_FILENAME, user_id); +} + +char *get_usim_filename(const char *output_dir, int user_id) { + return make_filename(output_dir, USIM_API_NVRAM_FILENAME, user_id); +} + +char *make_filename(const char *output_dir, const char *filename, int ueid) { + size_t size; + char *str_ueid, *str; + + str_ueid = itoa(ueid); + + if (str_ueid == NULL) { + perror("ERROR\t: itoa() failed"); + exit(EXIT_FAILURE); + } + + size = strlen(output_dir)+strlen(filename) + sizeof(ueid) + 1 + 1; // for \0 and for '/' + str = malloc(size); + if (str == NULL) { + perror("ERROR\t: make_filename() failed"); + exit(EXIT_FAILURE); + } + + snprintf(str, size, "%s/%s%s",output_dir, filename, str_ueid); + free(str_ueid); + + return str; +} diff --git a/openair3/NAS/TOOLS/fs.h b/openair3/NAS/TOOLS/fs.h new file mode 100644 index 0000000000000000000000000000000000000000..ecfca559550a2a440727f39045637a165209222d --- /dev/null +++ b/openair3/NAS/TOOLS/fs.h @@ -0,0 +1,12 @@ +#ifndef _FS_H +#define _FS_H + +#include <stdbool.h> + +bool file_exist_and_is_readable(const char *filename); +char *get_ue_filename(const char *output_dir, int user_id); +char *get_emm_filename(const char *output_dir, int user_id); +char *get_usim_filename(const char *output_dir, int user_id); +char *make_filename(const char *output_dir, const char *filename, int ueid); + +#endif diff --git a/openair3/NAS/TOOLS/network.h b/openair3/NAS/TOOLS/network.h index 0d60359c57b7d4093e2006e13c5c1f8a57e45619..d7044c8e51436792605078a8d79d04154e921107 100644 --- a/openair3/NAS/TOOLS/network.h +++ b/openair3/NAS/TOOLS/network.h @@ -61,7 +61,7 @@ Description Defines a list of PLMN network operators #define VDF5 11 -#define SELECTED_PLMN OAI_LTEBOX //SFR1 +#define SELECTED_PLMN TEST1 //SFR1 #define TEST_PLMN {0,0,0x0f,1,1,0} // 00101 #define SFR_PLMN_1 {0,2,0x0f,8,0,1} // 20810 diff --git a/openair3/NAS/TOOLS/nvram.c b/openair3/NAS/TOOLS/nvram.c new file mode 100644 index 0000000000000000000000000000000000000000..b10511f2fc94ca8f6acc92d2f08e235e54e61638 --- /dev/null +++ b/openair3/NAS/TOOLS/nvram.c @@ -0,0 +1,162 @@ +/* + * 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.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.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 + */ + +/***************************************************************************** +Source usim_data.c + +Version 0.1 + +Date 2012/10/31 + +Product NVRAM data generator + +Subsystem NVRAM data generator main process + +Author Frederic Maurel + +Description Implements the utility used to generate data stored in the + NVRAM application + + *****************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <getopt.h> + +#include "conf_parser.h" +#include "display.h" + +#define DEFAULT_NAS_PATH "PWD" +#define OUTPUT_DIR_ENV "NVRAM_DIR" +void _display_usage(const char* command); + +int main (int argc, char * const argv[]) +{ + enum usim_command { + NVRAM_COMMAND_NONE, + NVRAM_COMMAND_PRINT, + NVRAM_COMMAND_GEN, + } command = NVRAM_COMMAND_NONE; + + char *output_dir = NULL; + char *conf_file = NULL; + const char options[]="gpc:o:h"; + const struct option options_long_option[] = { + {"gen", no_argument, NULL, 'g'}, + {"print", no_argument, NULL, 'p'}, + {"conf", required_argument, NULL, 'c'}, + {"output", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + int option_index; + char option_short; + + /* + * Read command line parameters + */ + while ( true ) { + option_short = getopt_long(argc, argv, options, options_long_option, &option_index ); + + if ( option_short == -1 ) + break; + + switch (option_short) { + case 'c': + conf_file = optarg; + break; + case 'g': + command = NVRAM_COMMAND_GEN; + break; + case 'p': + command = NVRAM_COMMAND_PRINT; + break; + case 'o': + output_dir = optarg; + break; + default: + break; + } + } + + if ( command == NVRAM_COMMAND_NONE ) { + _display_usage(argv[0]); + exit(EXIT_SUCCESS); + } + + /* compute default data directory if no output_dir is given */ + if ( output_dir == NULL ) { + output_dir = getenv(OUTPUT_DIR_ENV); + + if (output_dir == NULL) { + output_dir = getenv(DEFAULT_NAS_PATH); + } + + if (output_dir == NULL) { + fprintf(stderr, "%s and %s environment variables are not defined trying local directory", + OUTPUT_DIR_ENV, DEFAULT_NAS_PATH); + output_dir = "."; + } + } + + if ( command == NVRAM_COMMAND_GEN ) { + if ( conf_file == NULL ) { + printf("No Configuration file is given\n"); + _display_usage(argv[0]); + exit(EXIT_FAILURE); + } + + if ( parse_config_file(output_dir, conf_file, OUTPUT_UEDATA|OUTPUT_EMM) == false ) { + exit(EXIT_FAILURE); + } + } + + if ( display_data_from_directory(output_dir, DISPLAY_UEDATA|DISPLAY_EMM) == 0) { + fprintf(stderr, "No NVRAM files found in %s\n", output_dir); + } + + exit(EXIT_SUCCESS); +} + +/****************************************************************************/ +/********************* L O C A L F U N C T I O N S *********************/ +/****************************************************************************/ + +/* + * Displays command line usage + */ +void _display_usage(const char* command) +{ + fprintf(stderr, "usage: %s [OPTION]\n", command); + fprintf(stderr, "\t[--gen|-g]\tGenerate the NVRAM data file\n"); + fprintf(stderr, "\t[--print|-p]\tDisplay the content of the NVRAM data file\n"); + fprintf(stderr, "\t[-c]\tConfig file to use\n"); + fprintf(stderr, "\t[-o]\toutput file directory\n"); + fprintf(stderr, "\t[--help|-h]\tDisplay this usage\n"); + const char* path = getenv("NVRAM_DIR"); + + if (path != NULL) { + fprintf(stderr, "NVRAM_DIR = %s\n", path); + } else { + fprintf(stderr, "NVRAM_DIR environment variable is not defined\n"); + } +} diff --git a/openair3/NAS/TOOLS/ue_bcom_test.conf b/openair3/NAS/TOOLS/ue_bcom_test.conf new file mode 100644 index 0000000000000000000000000000000000000000..c60b628941dbdc0090a567ec0ad67e575efc7b03 --- /dev/null +++ b/openair3/NAS/TOOLS/ue_bcom_test.conf @@ -0,0 +1,2334 @@ +PLMN: +{ + PLMN0: + { + FULLNAME="B<>COM Cubiq"; + SHORTNAME="BCOM"; + MNC="89"; + MCC="208"; + }; +}; + +UE0: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000000"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000000"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE1: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000001"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000001"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE2: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000002"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000002"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE3: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000003"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000003"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE4: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000004"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000004"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE5: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000005"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000005"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE6: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000006"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000006"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE7: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000007"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000007"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE8: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000008"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000008"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE9: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000009"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000009"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE10: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000010"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000010"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE11: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000011"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000011"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE12: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000012"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000012"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE13: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000013"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000013"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE14: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000014"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000014"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE15: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000015"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000015"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE16: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000016"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000016"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE17: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000017"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000017"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE18: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000018"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000018"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE19: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000019"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000019"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE20: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000020"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000020"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE21: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000021"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000021"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE22: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000022"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000022"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE23: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000023"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000023"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE24: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000024"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000024"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE25: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000025"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000025"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE26: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000026"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000026"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE27: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000027"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000027"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE28: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000028"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000028"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE29: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000029"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000029"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE30: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000030"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000030"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE31: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000031"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000031"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE32: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000032"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000032"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE33: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000033"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000033"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE34: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000034"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000034"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE35: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000035"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000035"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE36: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000036"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000036"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE37: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000037"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000037"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE38: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000038"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000038"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE39: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000039"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000039"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE40: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000040"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000040"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE41: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000041"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000041"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE42: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000042"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000042"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE43: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000043"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000043"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE44: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000044"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000044"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE45: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000045"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000045"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE46: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000046"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000046"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE47: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000047"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000047"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE48: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000048"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000048"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE49: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000049"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000049"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE50: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000050"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000050"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE51: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000051"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000051"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE52: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000052"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000052"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE53: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000053"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000053"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE54: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000054"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000054"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE55: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000055"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000055"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE56: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000056"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000056"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE57: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000057"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000057"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE58: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000058"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000058"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE59: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000059"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000059"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE60: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000060"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000060"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE61: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000061"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000061"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE62: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000062"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000062"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE63: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000063"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000063"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE64: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000064"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000064"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE65: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000065"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000065"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE66: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000066"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000066"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE67: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000067"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000067"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE68: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000068"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000068"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE69: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000069"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000069"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE70: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000070"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000070"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE71: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000071"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000071"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE72: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000072"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000072"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE73: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000073"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000073"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE74: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000074"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000074"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE75: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000075"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000075"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE76: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000076"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000076"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE77: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000077"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000077"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE78: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000078"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000078"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE79: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000079"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000079"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE80: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000080"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000080"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE81: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000081"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000081"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE82: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000082"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000082"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE83: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000083"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000083"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE84: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000084"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000084"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE85: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000085"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000085"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE86: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000086"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000086"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE87: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000087"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000087"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE88: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000088"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000088"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE89: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000089"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000089"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE90: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000090"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000090"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE91: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000091"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000091"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE92: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000092"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000092"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE93: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000093"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000093"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE94: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000094"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000094"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE95: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000095"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000095"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE96: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000096"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000096"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE97: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000097"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000097"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE98: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000098"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000098"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE99: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000099"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000099"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; +UE100: +{ +USER: + { + IMEI="35609204079299"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; +SIM: + { + MSIN="1000000100"; + USIM_API_K="00112233445566778899AABBCCDDEEFF"; + OPC="21C6FD3F84AA71BAC34FA8FCA0EAC64F"; + MSISDN="33600000100"; + }; +HPLMN= "20889"; +UCPLMN_LIST=(); +OPLMN_LIST=("20889"); +OCPLMN_LIST = (); +FPLMN_LIST = (); +EHPLMN_LIST= (); +}; diff --git a/openair3/NAS/TOOLS/ue_data.c b/openair3/NAS/TOOLS/ue_data.c deleted file mode 100644 index 3636ad6ee3d5519ecb61e81976f84a671be15bbe..0000000000000000000000000000000000000000 --- a/openair3/NAS/TOOLS/ue_data.c +++ /dev/null @@ -1,536 +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.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.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 - */ - -/***************************************************************************** -Source ue_data.c - -Version 0.1 - -Date 2012/11/02 - -Product UE data generator - -Subsystem UE data generator main process - -Author Frederic Maurel - -Description Implements the utility used to generate data stored in the - UE's non-volatile memory device - -*****************************************************************************/ - -#include "userDef.h" -#include "memory.h" - -#include "emmData.h" -#include "network.h" - -#include <stdio.h> // perror, printf, fprintf, snprintf -#include <stdlib.h> // exit, free -#include <string.h> // memset, strncpy - -/****************************************************************************/ -/**************** E X T E R N A L D E F I N I T I O N S ****************/ -/****************************************************************************/ - -#define USER_IMEI "35611302209414" -#define USER_MANUFACTURER "EURECOM" -#define USER_MODEL "LTE Android PC" -//#define USER_MANUFACTURER "SAGEM" -//#define USER_MODEL "my225x" -#define USER_PIN "0000" - -#define PRINT_PLMN_DIGIT(d) if ((d) != 0xf) printf("%u", (d)) - -#define PRINT_PLMN(plmn) \ - PRINT_PLMN_DIGIT((plmn).MCCdigit1); \ - PRINT_PLMN_DIGIT((plmn).MCCdigit2); \ - PRINT_PLMN_DIGIT((plmn).MCCdigit3); \ - PRINT_PLMN_DIGIT((plmn).MNCdigit1); \ - PRINT_PLMN_DIGIT((plmn).MNCdigit2); \ - PRINT_PLMN_DIGIT((plmn).MNCdigit3) - -/****************************************************************************/ -/******************* L O C A L D E F I N I T I O N S *******************/ -/****************************************************************************/ - -static void _display_usage(const char* command); - -static void _gen_user_data(user_nvdata_t* data); -static void _gen_emm_data(emm_nvdata_t* data); - -static int _luhn(const char* cc); -static void _display_ue_data(const user_nvdata_t* data); -static void _display_emm_data(const emm_nvdata_t* data); - -/****************************************************************************/ -/****************** E X P O R T E D F U N C T I O N S ******************/ -/****************************************************************************/ - -int main (int argc, const char* argv[]) -{ - int rc; - char* path; - user_nvdata_t user_data; - emm_nvdata_t emm_data; - - unsigned char gen_data; - - /* - * ---------------------------- - * Read command line parameters - * ---------------------------- - */ - if (argc != 2) { - fprintf(stderr, "Invalid parameter\n"); - _display_usage(argv[0]); - exit(EXIT_FAILURE); - } else if ( (strcmp(argv[1], "--gen") == 0) || - (strcmp(argv[1], "-g") == 0) ) { - /* Generate UE data files */ - gen_data = TRUE; - } else if ( (strcmp(argv[1], "--print") == 0) || - (strcmp(argv[1], "-p") == 0) ) { - /* Display content of UE data files */ - gen_data = FALSE; - } else { - /* Display usage */ - _display_usage(argv[0]); - exit(EXIT_SUCCESS); - } - /* - * ---------------------- - * UE's non-volatile data - * ---------------------- - */ - path = memory_get_path(USER_NVRAM_DIRNAME, USER_NVRAM_FILENAME); - - if (path == NULL) { - perror("ERROR\t: memory_get_path() failed"); - exit(EXIT_FAILURE); - } - - if (gen_data) { - /* - * Initialize UE's non-volatile data - */ - memset(&user_data, 0, sizeof(user_nvdata_t)); - _gen_user_data(&user_data); - /* - * Write UE's non-volatile data - */ - rc = memory_write(path, &user_data, sizeof(user_nvdata_t)); - - if (rc != RETURNok) { - perror("ERROR\t: memory_write() failed"); - free(path); - exit(EXIT_FAILURE); - } - } - - /* - * Read UE's non-volatile data - */ - memset(&user_data, 0, sizeof(user_nvdata_t)); - rc = memory_read(path, &user_data, sizeof(user_nvdata_t)); - - if (rc != RETURNok) { - perror("ERROR\t: memory_read() failed"); - free(path); - exit(EXIT_FAILURE); - } - - free(path); - /* - * Display UE's non-volatile data - */ - printf("\nUE's non-volatile data:\n\n"); - _display_ue_data(&user_data); - - /* - * --------------------- - * EMM non-volatile data - * --------------------- - */ - path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME); - - if (path == NULL) { - perror("ERROR\t: memory_get_path() failed"); - exit(EXIT_FAILURE); - } - - if (gen_data) { - /* - * Initialize EMM non-volatile data - */ - memset(&emm_data, 0, sizeof(emm_nvdata_t)); - _gen_emm_data(&emm_data); - /* - * Write EMM non-volatile data - */ - rc = memory_write(path, &emm_data, sizeof(emm_nvdata_t)); - - if (rc != RETURNok) { - perror("ERROR\t: memory_write() failed"); - free(path); - exit(EXIT_FAILURE); - } - } - - /* - * Read EMM non-volatile data - */ - memset(&emm_data, 0, sizeof(emm_nvdata_t)); - rc = memory_read(path, &emm_data, sizeof(emm_nvdata_t)); - - if (rc != RETURNok) { - perror("ERROR\t: memory_read() failed "); - free(path); - exit(EXIT_FAILURE); - } - - free(path); - /* - * Display EMM non-volatile data - */ - printf("\nEMM non-volatile data:\n\n"); - _display_emm_data(&emm_data); - - /* - *--------------- - * Files location - *--------------- - */ - path = memory_get_path(USER_NVRAM_DIRNAME, USER_NVRAM_FILENAME); - printf("\nUE identity data file: %s\n", path); - free(path); - path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME); - printf("EPS Mobility Management data file: %s\n", path); - free(path); - - exit(EXIT_SUCCESS); -} - -/****************************************************************************/ -/********************* L O C A L F U N C T I O N S *********************/ -/****************************************************************************/ - -/* - * Displays command line usage - */ -static void _display_usage(const char* command) -{ - fprintf(stderr, "usage: %s [OPTION]\n", command); - fprintf(stderr, "\t[--gen|-g]\tGenerate the UE data files\n"); - fprintf(stderr, "\t[--print|-p]\tDisplay the content of the UE data files\n"); - fprintf(stderr, "\t[--help|-h]\tDisplay this usage\n"); - const char* path = getenv("NVRAM_DIR"); - - if (path != NULL) { - fprintf(stderr, "NVRAM_DIR = %s\n", path); - } else { - fprintf(stderr, "NVRAM_DIR environment variable is not defined\n"); - } -} - -/* - * Generates UE's non-volatile data - */ -static void _gen_user_data(user_nvdata_t* data) -{ - /* - * Product Serial Number Identification - * IMEI = AA-BBBBBB-CCCCCC-D - * AA-BBBBBB: Type Allocation Code (TAC) - * CCCCCC: Serial Number - * D: Luhn check digit - */ - snprintf(data->IMEI, USER_IMEI_SIZE+1, "%s%d", - USER_IMEI, _luhn(USER_IMEI)); - /* - * Manufacturer identifier - */ - strncpy(data->manufacturer, USER_MANUFACTURER, USER_MANUFACTURER_SIZE); - /* - * Model identifier - */ - strncpy(data->model, USER_MODEL, USER_MODEL_SIZE); - /* - * SIM Personal Identification Number - */ - strncpy(data->PIN, USER_PIN, USER_PIN_SIZE); -} - -/* - * Generates UE's non-volatile EMM data - */ -static void _gen_emm_data(emm_nvdata_t* data) -{ -#if (SELECTED_PLMN == FCT1) - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 310 (USA) + 028 (UNKNOWN) + 90832150 - */ -#warning "IMSI 310.028.90832150" - data->imsi.length = 8; - data->imsi.u.num.parity = 0x0; // Type of identity = IMSI, even - data->imsi.u.num.digit1 = 3; // MCC digit 1 - data->imsi.u.num.digit2 = 1; // MCC digit 2 - data->imsi.u.num.digit3 = 0; // MCC digit 3 - data->imsi.u.num.digit4 = 0; // MNC digit 1 - data->imsi.u.num.digit5 = 2; // MNC digit 2 - data->imsi.u.num.digit6 = 8; // MNC digit 3 - data->imsi.u.num.digit7 = 9; - data->imsi.u.num.digit8 = 0; - data->imsi.u.num.digit9 = 8; - data->imsi.u.num.digit10 = 3; - data->imsi.u.num.digit11 = 2; - data->imsi.u.num.digit12 = 1; - data->imsi.u.num.digit13 = 5; - data->imsi.u.num.digit14 = 0; - data->imsi.u.num.digit15 = 0xF; - /* - * Last registered home PLMN - */ - data->rplmn.MCCdigit1 = 3; - data->rplmn.MCCdigit2 = 1; - data->rplmn.MCCdigit3 = 0; - data->rplmn.MNCdigit1 = 0; - data->rplmn.MNCdigit2 = 2; - data->rplmn.MNCdigit3 = 8; -#endif -#if (SELECTED_PLMN == SFR1) - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 208 (France) + 10 (SFR) + 00001234 - */ - data->imsi.length = 8; - data->imsi.u.num.parity = 0x0; // Type of identity = IMSI, even - data->imsi.u.num.digit1 = 2; // MCC digit 1 - data->imsi.u.num.digit2 = 0; // MCC digit 2 - data->imsi.u.num.digit3 = 8; // MCC digit 3 - data->imsi.u.num.digit4 = 1; // MNC digit 1 - data->imsi.u.num.digit5 = 0; // MNC digit 2 - data->imsi.u.num.digit6 = 0;//0xF; // MNC digit 3 - data->imsi.u.num.digit7 = 0; - data->imsi.u.num.digit8 = 0; - data->imsi.u.num.digit9 = 0; - data->imsi.u.num.digit10 = 0; - data->imsi.u.num.digit11 = 1; - data->imsi.u.num.digit12 = 2; - data->imsi.u.num.digit13 = 3; - data->imsi.u.num.digit14 = 4; - data->imsi.u.num.digit15 = 0xF; - - data->rplmn.MCCdigit1 = 2; - data->rplmn.MCCdigit2 = 0; - data->rplmn.MCCdigit3 = 8; - data->rplmn.MNCdigit1 = 1; - data->rplmn.MNCdigit2 = 0; - data->rplmn.MNCdigit3 = 0xf; -#endif -#if (SELECTED_PLMN == OAI_LTEBOX) - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 208 (France) + 93 (OAI) + 00001110 - */ - data->imsi.length = 8; - data->imsi.u.num.parity = ODD_PARITY; // Type of identity = IMSI, even - data->imsi.u.num.digit1 = 2; // MCC digit 1 - data->imsi.u.num.digit2 = 0; // MCC digit 2 - data->imsi.u.num.digit3 = 8; // MCC digit 3 - data->imsi.u.num.digit4 = 9; // MNC digit 1 - data->imsi.u.num.digit5 = 3; // MNC digit 2 - data->imsi.u.num.digit6 = 0; // MNC digit 3 - data->imsi.u.num.digit7 = 1; - data->imsi.u.num.digit8 = 0; - data->imsi.u.num.digit9 = 0; - data->imsi.u.num.digit10 = 0; - data->imsi.u.num.digit11 = 0; - data->imsi.u.num.digit12 = 1; - data->imsi.u.num.digit13 = 1; - data->imsi.u.num.digit14 = 1; - data->imsi.u.num.digit15 = 1; - - data->rplmn.MCCdigit1 = 2; - data->rplmn.MCCdigit2 = 0; - data->rplmn.MCCdigit3 = 8; - data->rplmn.MNCdigit1 = 9; - data->rplmn.MNCdigit2 = 3; - data->rplmn.MNCdigit3 = 0xf; -#endif -#if (SELECTED_PLMN == TEST1) - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 001 + 01 + 00001234 - */ - data->imsi.length = 8; - data->imsi.u.num.parity = 0x0; // Type of identity = IMSI, even - data->imsi.u.num.digit1 = 0; // MCC digit 1 - data->imsi.u.num.digit2 = 0; // MCC digit 2 - data->imsi.u.num.digit3 = 1; // MCC digit 3 - data->imsi.u.num.digit4 = 0; // MNC digit 1 - data->imsi.u.num.digit5 = 1; // MNC digit 2 - data->imsi.u.num.digit6 = 0; - data->imsi.u.num.digit7 = 0; - data->imsi.u.num.digit8 = 0; - data->imsi.u.num.digit9 = 0; - data->imsi.u.num.digit10 = 0; - data->imsi.u.num.digit11 = 1; - data->imsi.u.num.digit12 = 2; - data->imsi.u.num.digit13 = 3; - data->imsi.u.num.digit14 = 4; - data->imsi.u.num.digit15 = 0xF; - - /* - * Last registered home PLMN - */ - data->rplmn.MCCdigit1 = 0; - data->rplmn.MCCdigit2 = 0; - data->rplmn.MCCdigit3 = 1; - data->rplmn.MNCdigit1 = 0; - data->rplmn.MNCdigit2 = 1; - data->rplmn.MNCdigit3 = 0xf; -#endif - /* - * List of Equivalent PLMNs - */ - data->eplmn.n_plmns = 0; -} - -/* - * Computes the check digit using Luhn algorithm - */ -static int _luhn(const char* cc) -{ - const int m[] = {0,2,4,6,8,1,3,5,7,9}; - int odd = 1, sum = 0; - - for (int i = strlen(cc); i--; odd = !odd) { - int digit = cc[i] - '0'; - sum += odd ? m[digit] : digit; - } - - return 10 - (sum % 10); -} - -/* - * Displays UE's non-volatile data - */ -static void _display_ue_data(const user_nvdata_t* data) -{ - printf("IMEI\t\t= %s\n", data->IMEI); - printf("manufacturer\t= %s\n", data->manufacturer); - printf("model\t\t= %s\n", data->model); - printf("PIN\t\t= %s\n", data->PIN); -} - -/* - * Displays UE's non-volatile EMM data - */ -static void _display_emm_data(const emm_nvdata_t* data) -{ - printf("IMSI\t\t= "); - - if (data->imsi.u.num.digit6 == 0b1111) { - if (data->imsi.u.num.digit15 == 0b1111) { - printf("%u%u%u.%u%u.%u%u%u%u%u%u%u%u\n", - data->imsi.u.num.digit1, - data->imsi.u.num.digit2, - data->imsi.u.num.digit3, - data->imsi.u.num.digit4, - data->imsi.u.num.digit5, - - data->imsi.u.num.digit7, - data->imsi.u.num.digit8, - data->imsi.u.num.digit9, - data->imsi.u.num.digit10, - data->imsi.u.num.digit11, - data->imsi.u.num.digit12, - data->imsi.u.num.digit13, - data->imsi.u.num.digit14); - } else { - printf("%u%u%u.%u%u.%u%u%u%u%u%u%u%u%u\n", - data->imsi.u.num.digit1, - data->imsi.u.num.digit2, - data->imsi.u.num.digit3, - data->imsi.u.num.digit4, - data->imsi.u.num.digit5, - - data->imsi.u.num.digit7, - data->imsi.u.num.digit8, - data->imsi.u.num.digit9, - data->imsi.u.num.digit10, - data->imsi.u.num.digit11, - data->imsi.u.num.digit12, - data->imsi.u.num.digit13, - data->imsi.u.num.digit14, - data->imsi.u.num.digit15); - } - } else { - if (data->imsi.u.num.digit15 == 0b1111) { - printf("%u%u%u.%u%u%u.%u%u%u%u%u%u%u%u\n", - data->imsi.u.num.digit1, - data->imsi.u.num.digit2, - data->imsi.u.num.digit3, - data->imsi.u.num.digit4, - data->imsi.u.num.digit5, - data->imsi.u.num.digit6, - - data->imsi.u.num.digit7, - data->imsi.u.num.digit8, - data->imsi.u.num.digit9, - data->imsi.u.num.digit10, - data->imsi.u.num.digit11, - data->imsi.u.num.digit12, - data->imsi.u.num.digit13, - data->imsi.u.num.digit14); - } else { - printf("%u%u%u.%u%u%u.%u%u%u%u%u%u%u%u%u\n", - data->imsi.u.num.digit1, - data->imsi.u.num.digit2, - data->imsi.u.num.digit3, - data->imsi.u.num.digit4, - data->imsi.u.num.digit5, - data->imsi.u.num.digit6, - - data->imsi.u.num.digit7, - data->imsi.u.num.digit8, - data->imsi.u.num.digit9, - data->imsi.u.num.digit10, - data->imsi.u.num.digit11, - data->imsi.u.num.digit12, - data->imsi.u.num.digit13, - data->imsi.u.num.digit14, - data->imsi.u.num.digit15); - } - } - - printf("RPLMN\t\t= "); - PRINT_PLMN(data->rplmn); - printf("\n"); - - for (int i = 0; i < data->eplmn.n_plmns; i++) { - printf("EPLMN[%d]\t= ", i); - PRINT_PLMN(data->eplmn.plmn[i]); - printf("\n"); - } -} diff --git a/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf b/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf new file mode 100644 index 0000000000000000000000000000000000000000..84ec59a36bcb9906c8f9010a7dabfbfb2e62412e --- /dev/null +++ b/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf @@ -0,0 +1,114 @@ +# List of known PLMNS +PLMN: { + PLMN0: { + FULLNAME="Test network"; + SHORTNAME="OAI4G"; + MNC="01"; + MCC="001"; + + }; + PLMN1: { + FULLNAME="SFR France"; + SHORTNAME="SFR"; + MNC="10"; + MCC="208"; + + }; + PLMN2: { + FULLNAME="SFR France"; + SHORTNAME="SFR"; + MNC="11"; + MCC="208"; + }; + PLMN3: { + FULLNAME="SFR France"; + SHORTNAME="SFR"; + MNC="13"; + MCC="208"; + }; + PLMN4: { + FULLNAME="OAI LTEBOX"; + SHORTNAME="OAIALU"; + MNC="93"; + MCC="208"; + }; + PLMN5: { + FULLNAME="T-Mobile USA"; + SHORTNAME="T-Mobile"; + MNC="280"; + MCC="310"; + }; + PLMN6: { + FULLNAME="FICTITIOUS USA"; + SHORTNAME="FICTITIO"; + MNC="028"; + MCC="310"; + }; + PLMN7: { + FULLNAME="Vodafone Italia"; + SHORTNAME="VODAFONE"; + MNC="10"; + MCC="222"; + }; + PLMN8: { + FULLNAME="Vodafone Spain"; + SHORTNAME="VODAFONE"; + MNC="01"; + MCC="214"; + }; + PLMN9: { + FULLNAME="Vodafone Spain"; + SHORTNAME="VODAFONE"; + MNC="06"; + MCC="214"; + }; + PLMN10: { + FULLNAME="Vodafone Germ"; + SHORTNAME="VODAFONE"; + MNC="02"; + MCC="262"; + }; + PLMN11: { + FULLNAME="Vodafone Germ"; + SHORTNAME="VODAFONE"; + MNC="04"; + MCC="262"; + }; +}; + +UE0: +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; + + SIM: { + MSIN="0100001111"; + USIM_API_K="fec86ba6eb707ed08905757b1bb44b8f"; + OPC="C42449363BBAD02B66D16BC975D77CC1"; + MSISDN="33611123456"; + }; + + # Home PLMN Selector with Access Technology + HPLMN= "20893"; + + # User controlled PLMN Selector with Access Technology + UCPLMN_LIST = (); + + # Operator PLMN List + OPLMN_LIST = ("00101", "20810", "20811", "20813", "20893", "310280", "310028"); + + # Operator controlled PLMN Selector with Access Technology + OCPLMN_LIST = ("22210", "21401", "21406", "26202", "26204"); + + # Forbidden plmns + FPLMN_LIST = (); + + # List of Equivalent HPLMNs +#TODO: UE does not connect if set, to be fixed in the UE +# EHPLMN_LIST= ("20811", "20813"); + EHPLMN_LIST= (); +}; diff --git a/openair3/NAS/TOOLS/ue_tcl_test.conf b/openair3/NAS/TOOLS/ue_tcl_test.conf new file mode 100644 index 0000000000000000000000000000000000000000..05db6be4d12130603fec8d272bf102158d8f23a4 --- /dev/null +++ b/openair3/NAS/TOOLS/ue_tcl_test.conf @@ -0,0 +1,114 @@ +# List of known PLMNS +PLMN: { + PLMN0: { + FULLNAME="Test network"; + SHORTNAME="OAI4G"; + MNC="01"; + MCC="001"; + + }; + PLMN1: { + FULLNAME="SFR France"; + SHORTNAME="SFR"; + MNC="10"; + MCC="208"; + + }; + PLMN2: { + FULLNAME="SFR France"; + SHORTNAME="SFR"; + MNC="11"; + MCC="208"; + }; + PLMN3: { + FULLNAME="SFR France"; + SHORTNAME="SFR"; + MNC="13"; + MCC="208"; + }; + PLMN4: { + FULLNAME="OAI LTEBOX"; + SHORTNAME="OAIALU"; + MNC="93"; + MCC="208"; + }; + PLMN5: { + FULLNAME="T-Mobile USA"; + SHORTNAME="T-Mobile"; + MNC="280"; + MCC="310"; + }; + PLMN6: { + FULLNAME="FICTITIOUS USA"; + SHORTNAME="FICTITIO"; + MNC="028"; + MCC="310"; + }; + PLMN7: { + FULLNAME="Vodafone Italia"; + SHORTNAME="VODAFONE"; + MNC="10"; + MCC="222"; + }; + PLMN8: { + FULLNAME="Vodafone Spain"; + SHORTNAME="VODAFONE"; + MNC="01"; + MCC="214"; + }; + PLMN9: { + FULLNAME="Vodafone Spain"; + SHORTNAME="VODAFONE"; + MNC="06"; + MCC="214"; + }; + PLMN10: { + FULLNAME="Vodafone Germ"; + SHORTNAME="VODAFONE"; + MNC="02"; + MCC="262"; + }; + PLMN11: { + FULLNAME="Vodafone Germ"; + SHORTNAME="VODAFONE"; + MNC="04"; + MCC="262"; + }; +}; + +UE0: +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; + + SIM: { + MSIN="000001234"; + USIM_API_K="000102030405060708090A0B0C0D0E0F"; + OPC="C42449363BBAD02B66D16BC975D77CC1"; + MSISDN="000000000000";//"33611123456"; + }; + + # Home PLMN Selector with Access Technology + HPLMN= "00101"; + + # User controlled PLMN Selector with Access Technology + UCPLMN_LIST = (); + + # Operator PLMN List + OPLMN_LIST = ("00101", "20810", "20811", "20813", "20893", "310280", "310028"); + + # Operator controlled PLMN Selector with Access Technology + OCPLMN_LIST = ("22210", "21401", "21406", "26202", "26204"); + + # Forbidden plmns + FPLMN_LIST = (); + + # List of Equivalent HPLMNs +#TODO: UE does not connect if set, to be fixed in the UE +# EHPLMN_LIST= ("20811", "20813"); + EHPLMN_LIST= (); +}; diff --git a/openair3/NAS/TOOLS/usim.c b/openair3/NAS/TOOLS/usim.c new file mode 100644 index 0000000000000000000000000000000000000000..242b30d65558e3a1c4f31aa89f61267bcac533a0 --- /dev/null +++ b/openair3/NAS/TOOLS/usim.c @@ -0,0 +1,162 @@ +/* + * 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.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.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 + */ + +/***************************************************************************** +Source usim_data.c + +Version 0.1 + +Date 2012/10/31 + +Product USIM data generator + +Subsystem USIM data generator main process + +Author Frederic Maurel + +Description Implements the utility used to generate data stored in the + USIM application + + *****************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <getopt.h> + +#include "conf_parser.h" +#include "display.h" + +#define DEFAULT_NAS_PATH "PWD" +#define OUTPUT_DIR_ENV "USIM_DIR" +void _display_usage(const char* command); + +int main (int argc, char * const argv[]) +{ + enum usim_command { + USIM_COMMAND_NONE, + USIM_COMMAND_PRINT, + USIM_COMMAND_GEN, + } command = USIM_COMMAND_NONE; + + char *output_dir = NULL; + char *conf_file = NULL; + const char options[]="gpc:o:h"; + const struct option options_long_option[] = { + {"gen", no_argument, NULL, 'g'}, + {"print", no_argument, NULL, 'p'}, + {"conf", required_argument, NULL, 'c'}, + {"output", required_argument, NULL, 'o'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + int option_index; + char option_short; + + /* + * Read command line parameters + */ + while ( true ) { + option_short = getopt_long(argc, argv, options, options_long_option, &option_index ); + + if ( option_short == -1 ) + break; + + switch (option_short) { + case 'c': + conf_file = optarg; + break; + case 'g': + command = USIM_COMMAND_GEN; + break; + case 'p': + command = USIM_COMMAND_PRINT; + break; + case 'o': + output_dir = optarg; + break; + default: + break; + } + } + + if ( command == USIM_COMMAND_NONE ) { + _display_usage(argv[0]); + exit(EXIT_SUCCESS); + } + + /* compute default data directory if no output_dir is given */ + if ( output_dir == NULL ) { + output_dir = getenv(OUTPUT_DIR_ENV); + + if (output_dir == NULL) { + output_dir = getenv(DEFAULT_NAS_PATH); + } + + if (output_dir == NULL) { + fprintf(stderr, "%s and %s environment variables are not defined trying local directory", + OUTPUT_DIR_ENV, DEFAULT_NAS_PATH); + output_dir = "."; + } + } + + if ( command == USIM_COMMAND_GEN ) { + if ( conf_file == NULL ) { + printf("No Configuration file is given\n"); + _display_usage(argv[0]); + exit(EXIT_FAILURE); + } + + if ( parse_config_file(output_dir, conf_file, OUTPUT_USIM) == false ) { + exit(EXIT_FAILURE); + } + } + + if ( display_data_from_directory(output_dir, DISPLAY_USIM) == 0) { + fprintf(stderr, "No USIM files found in %s\n", output_dir); + } + + exit(EXIT_SUCCESS); +} + +/****************************************************************************/ +/********************* L O C A L F U N C T I O N S *********************/ +/****************************************************************************/ + +/* + * Displays command line usage + */ +void _display_usage(const char* command) +{ + fprintf(stderr, "usage: %s [OPTION]\n", command); + fprintf(stderr, "\t[--gen|-g]\tGenerate the USIM data file\n"); + fprintf(stderr, "\t[--print|-p]\tDisplay the content of the USIM data file\n"); + fprintf(stderr, "\t[-c]\tConfig file to use\n"); + fprintf(stderr, "\t[-o]\toutput file directory\n"); + fprintf(stderr, "\t[--help|-h]\tDisplay this usage\n"); + const char* path = getenv("USIM_DIR"); + + if (path != NULL) { + fprintf(stderr, "USIM_DIR = %s\n", path); + } else { + fprintf(stderr, "USIM_DIR environment variable is not defined\n"); + } +} diff --git a/openair3/NAS/TOOLS/usim_data.c b/openair3/NAS/TOOLS/usim_data.c deleted file mode 100644 index 23eba29bb134cf1fa3ad8a9bacec4f546d23cd96..0000000000000000000000000000000000000000 --- a/openair3/NAS/TOOLS/usim_data.c +++ /dev/null @@ -1,659 +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.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.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 - */ - -/***************************************************************************** -Source usim_data.c - -Version 0.1 - -Date 2012/10/31 - -Product USIM data generator - -Subsystem USIM data generator main process - -Author Frederic Maurel - -Description Implements the utility used to generate data stored in the - USIM application - - *****************************************************************************/ - -#include "network.h" - -#include "usim_api.h" -#include "memory.h" -#include "network.h" - -#include <stdio.h> // perror, printf -#include <stdlib.h> // exit -#include <string.h> // memset, memcpy, strncpy - - -/****************************************************************************/ -/**************** E X T E R N A L D E F I N I T I O N S ****************/ -/****************************************************************************/ - -#define KSI USIM_KSI_NOT_AVAILABLE -#define KSI_ASME USIM_KSI_NOT_AVAILABLE -#define INT_ALGO USIM_INT_EIA2 -#define ENC_ALGO USIM_ENC_EEA0 -#define SECURITY_ALGORITHMS (ENC_ALGO | INT_ALGO) - -#define MIN_TAC 0x0000 -#define MAX_TAC 0xFFFE - -#define DEFAULT_TMSI 0x0000000D -#define DEFAULT_P_TMSI 0x0000000D -#define DEFAULT_M_TMSI 0x0000000D -#define DEFAULT_LAC 0xFFFE -#define DEFAULT_RAC 0x01 -#define DEFAULT_TAC 0x0001 - -#define DEFAULT_MME_ID 0x0102 -#define DEFAULT_MME_CODE 0x0F - -#define PRINT_PLMN_DIGIT(d) if ((d) != 0xf) printf("%u", (d)) - -#define PRINT_PLMN(plmn) \ - PRINT_PLMN_DIGIT((plmn).MCCdigit1); \ - PRINT_PLMN_DIGIT((plmn).MCCdigit2); \ - PRINT_PLMN_DIGIT((plmn).MCCdigit3); \ - PRINT_PLMN_DIGIT((plmn).MNCdigit1); \ - PRINT_PLMN_DIGIT((plmn).MNCdigit2); \ - PRINT_PLMN_DIGIT((plmn).MNCdigit3) - -/****************************************************************************/ -/******************* L O C A L D E F I N I T I O N S *******************/ -/****************************************************************************/ - -static void _display_usage(const char* command); - -static void _display_usim_data(const usim_data_t* data); - -/****************************************************************************/ -/****************** E X P O R T E D F U N C T I O N S ******************/ -/****************************************************************************/ - -int main (int argc, const char* argv[]) -{ - int rc; - usim_data_t usim_data; - - unsigned char gen_data; - - /* - * Read command line parameters - */ - if (argc != 2) { - fprintf(stderr, "Invalid parameter\n"); - _display_usage(argv[0]); - exit(EXIT_FAILURE); - } else if ( (strcmp(argv[1], "--gen") == 0) || - (strcmp(argv[1], "-g") == 0) ) { - /* Generate USIM data files */ - gen_data = TRUE; - } else if ( (strcmp(argv[1], "--print") == 0) || - (strcmp(argv[1], "-p") == 0) ) { - /* Display content of USIM data files */ - gen_data = FALSE; - } else { - /* Display usage */ - _display_usage(argv[0]); - exit(EXIT_SUCCESS); - } - - if (gen_data) { - /* - * Initialize USIM data - */ - memset(&usim_data, 0, sizeof(usim_data_t)); - -#if (SELECTED_PLMN == FCT1) - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 310 (USA) + 028 (UNKNOWN) + 90832150 - */ -#warning "IMSI 310.028.90832150" - usim_data.imsi.length = 8; - usim_data.imsi.u.num.parity = EVEN_PARITY; // Parity: even - usim_data.imsi.u.num.digit1 = 3; // MCC digit 1 - usim_data.imsi.u.num.digit2 = 1; // MCC digit 2 - usim_data.imsi.u.num.digit3 = 0; // MCC digit 3 - usim_data.imsi.u.num.digit4 = 0; // MNC digit 1 - usim_data.imsi.u.num.digit5 = 2; // MNC digit 2 - usim_data.imsi.u.num.digit6 = 8; // MNC digit 3 - usim_data.imsi.u.num.digit7 = 9; - usim_data.imsi.u.num.digit8 = 0; - usim_data.imsi.u.num.digit9 = 8; - usim_data.imsi.u.num.digit10 = 3; - usim_data.imsi.u.num.digit11 = 2; - usim_data.imsi.u.num.digit12 = 1; - usim_data.imsi.u.num.digit13 = 5; - usim_data.imsi.u.num.digit14 = 0; - usim_data.imsi.u.num.digit15 = 0b1111; -#endif -#if (SELECTED_PLMN == SFR1) - - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 208 (France) + 10 (SFR) + 00001234 - */ -#warning "IMSI 208.10.00001234" - - usim_data.imsi.length = 8; - usim_data.imsi.u.num.parity = EVEN_PARITY; // Parity: even - usim_data.imsi.u.num.digit1 = 2; // MCC digit 1 - usim_data.imsi.u.num.digit2 = 0; // MCC digit 2 - usim_data.imsi.u.num.digit3 = 8; // MCC digit 3 - usim_data.imsi.u.num.digit4 = 1; // MNC digit 1 - usim_data.imsi.u.num.digit5 = 0; // MNC digit 2 - usim_data.imsi.u.num.digit6 = 0;//0b1111; // MNC digit 3 - usim_data.imsi.u.num.digit7 = 0; - usim_data.imsi.u.num.digit8 = 0; - usim_data.imsi.u.num.digit9 = 0; - usim_data.imsi.u.num.digit10 = 0; - usim_data.imsi.u.num.digit11 = 1; - usim_data.imsi.u.num.digit12 = 2; - usim_data.imsi.u.num.digit13 = 3; - usim_data.imsi.u.num.digit14 = 4; - usim_data.imsi.u.num.digit15 = 0b1111; -#endif -#if (SELECTED_PLMN == OAI_LTEBOX) - /* - * International Mobile Subscriber Identity - * IMSI = MCC + MNC + MSIN = 208 (France) + 10 (SFR) + 00001234 - */ -#warning "IMSI 208.93.0100001111" - usim_data.imsi.length = 8; - usim_data.imsi.u.num.parity = ODD_PARITY; // Parity: even - usim_data.imsi.u.num.digit1 = 2; // MCC digit 1 - usim_data.imsi.u.num.digit2 = 0; // MCC digit 2 - usim_data.imsi.u.num.digit3 = 8; // MCC digit 3 - usim_data.imsi.u.num.digit4 = 9; // MNC digit 1 - usim_data.imsi.u.num.digit5 = 3; // MNC digit 2 - usim_data.imsi.u.num.digit6 = 0; // MNC digit 3 - usim_data.imsi.u.num.digit7 = 1; - usim_data.imsi.u.num.digit8 = 0; - usim_data.imsi.u.num.digit9 = 0; - usim_data.imsi.u.num.digit10 = 0; - usim_data.imsi.u.num.digit11 = 0; - usim_data.imsi.u.num.digit12 = 1; - usim_data.imsi.u.num.digit13 = 1; - usim_data.imsi.u.num.digit14 = 1; - usim_data.imsi.u.num.digit15 = 1; -#endif -#if (SELECTED_PLMN == TEST1) -#warning "IMSI 001.01.000001234" - usim_data.imsi.length = 8; - usim_data.imsi.u.num.parity = 0x0; // Type of identity = IMSI, even - usim_data.imsi.u.num.digit1 = 0; // MCC digit 1 - usim_data.imsi.u.num.digit2 = 0; // MCC digit 2 - usim_data.imsi.u.num.digit3 = 1; // MCC digit 3 - usim_data.imsi.u.num.digit4 = 0; // MNC digit 1 - usim_data.imsi.u.num.digit5 = 1; // MNC digit 2 - usim_data.imsi.u.num.digit6 = 0; - usim_data.imsi.u.num.digit7 = 0; - usim_data.imsi.u.num.digit8 = 0; - usim_data.imsi.u.num.digit9 = 0; - usim_data.imsi.u.num.digit10 = 0; - usim_data.imsi.u.num.digit11 = 1; - usim_data.imsi.u.num.digit12 = 2; - usim_data.imsi.u.num.digit13 = 3; - usim_data.imsi.u.num.digit14 = 4; - usim_data.imsi.u.num.digit15 = 0xF; - usim_data.usimtestmode = 1; // set usim in test mode in order to get the CMW500 K key -#endif - /* - * Ciphering and Integrity Keys - */ - usim_data.keys.ksi = KSI; - memset(&usim_data.keys.ck, 0, USIM_CK_SIZE); - memset(&usim_data.keys.ik, 0, USIM_IK_SIZE); - - /* - * Higher Priority PLMN search period - */ - usim_data.hpplmn = 0x00; /* Disable timer */ - - /* - * List of Forbidden PLMNs - */ - for (int i = 0; i < USIM_FPLMN_MAX; i++) { - memset(&usim_data.fplmn[i], 0xff, sizeof(plmn_t)); - } - - /* - * Location Information - */ - usim_data.loci.tmsi = DEFAULT_TMSI; - usim_data.loci.lai.plmn = network_records[SELECTED_PLMN].plmn; - usim_data.loci.lai.lac = DEFAULT_LAC; - usim_data.loci.status = USIM_LOCI_NOT_UPDATED; - /* - * Packet Switched Location Information - */ - usim_data.psloci.p_tmsi = DEFAULT_P_TMSI; - usim_data.psloci.signature[0] = 0x01; - usim_data.psloci.signature[1] = 0x02; - usim_data.psloci.signature[2] = 0x03; - usim_data.psloci.rai.plmn = network_records[SELECTED_PLMN].plmn; - usim_data.psloci.rai.lac = DEFAULT_LAC; - usim_data.psloci.rai.rac = DEFAULT_RAC; - usim_data.psloci.status = USIM_PSLOCI_NOT_UPDATED; - /* - * Administrative Data - */ - usim_data.ad.UE_Operation_Mode = USIM_NORMAL_MODE; - usim_data.ad.Additional_Info = 0xffff; - usim_data.ad.MNC_Length = 2; - /* - * EPS NAS security context - */ - usim_data.securityctx.length = 52; - usim_data.securityctx.KSIasme.type = USIM_KSI_ASME_TAG; - usim_data.securityctx.KSIasme.length = 1; - usim_data.securityctx.KSIasme.value[0] = KSI_ASME; - usim_data.securityctx.Kasme.type = USIM_K_ASME_TAG; - usim_data.securityctx.Kasme.length = USIM_K_ASME_SIZE; - memset(usim_data.securityctx.Kasme.value, 0, - usim_data.securityctx.Kasme.length); - usim_data.securityctx.ulNAScount.type = USIM_UL_NAS_COUNT_TAG; - usim_data.securityctx.ulNAScount.length = USIM_UL_NAS_COUNT_SIZE; - memset(usim_data.securityctx.ulNAScount.value, 0, - usim_data.securityctx.ulNAScount.length); - usim_data.securityctx.dlNAScount.type = USIM_DL_NAS_COUNT_TAG; - usim_data.securityctx.dlNAScount.length = USIM_DL_NAS_COUNT_SIZE; - memset(usim_data.securityctx.dlNAScount.value, 0, - usim_data.securityctx.dlNAScount.length); - usim_data.securityctx.algorithmID.type = USIM_INT_ENC_ALGORITHMS_TAG; - usim_data.securityctx.algorithmID.length = 1; - usim_data.securityctx.algorithmID.value[0] = SECURITY_ALGORITHMS; - /* - * Subcriber's Number - */ - usim_data.msisdn.length = 7; - usim_data.msisdn.number.ext = 1; - usim_data.msisdn.number.ton = MSISDN_TON_UNKNOWKN; - usim_data.msisdn.number.npi = MSISDN_NPI_ISDN_TELEPHONY; - usim_data.msisdn.number.digit[0].msb = 3; - usim_data.msisdn.number.digit[0].lsb = 3; - usim_data.msisdn.number.digit[1].msb = 6; - usim_data.msisdn.number.digit[1].lsb = 1; - usim_data.msisdn.number.digit[2].msb = 1; - usim_data.msisdn.number.digit[2].lsb = 1; - usim_data.msisdn.number.digit[3].msb = 2; - usim_data.msisdn.number.digit[3].lsb = 3; - usim_data.msisdn.number.digit[4].msb = 4; - usim_data.msisdn.number.digit[4].lsb = 5; - usim_data.msisdn.number.digit[5].msb = 6; - usim_data.msisdn.number.digit[5].lsb = 0xf; - usim_data.msisdn.number.digit[6].msb = 0xf; - usim_data.msisdn.number.digit[6].lsb = 0xf; - usim_data.msisdn.number.digit[7].msb = 0xf; - usim_data.msisdn.number.digit[7].lsb = 0xf; - usim_data.msisdn.number.digit[8].msb = 0xf; - usim_data.msisdn.number.digit[8].lsb = 0xf; - usim_data.msisdn.number.digit[9].msb = 0xf; - usim_data.msisdn.number.digit[9].lsb = 0xf; - usim_data.msisdn.conf1_record_id = 0xff; /* Not used */ - usim_data.msisdn.ext1_record_id = 0xff; /* Not used */ - - /* - * PLMN Network Name and Operator PLMN List - */ - for (int i = TEST1; i < VDF1; i++) { - network_record_t record = network_records[i]; - usim_data.pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG; - usim_data.pnn[i].fullname.length = strlen(record.fullname); - strncpy((char*)usim_data.pnn[i].fullname.value, record.fullname, - usim_data.pnn[i].fullname.length); - usim_data.pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG; - usim_data.pnn[i].shortname.length = strlen(record.shortname); - strncpy((char*)usim_data.pnn[i].shortname.value, record.shortname, - usim_data.pnn[i].shortname.length); - usim_data.opl[i].plmn = record.plmn; - usim_data.opl[i].start = record.tac_start; - usim_data.opl[i].end = record.tac_end; - usim_data.opl[i].record_id = i; - } - - for (int i = VDF2; i < USIM_OPL_MAX; i++) { - memset(&usim_data.opl[i].plmn, 0xff, sizeof(plmn_t)); - } - - /* - * List of Equivalent HPLMNs - */ - usim_data.ehplmn[0] = network_records[SFR2].plmn; - usim_data.ehplmn[1] = network_records[SFR3].plmn; - /* - * Home PLMN Selector with Access Technology - */ - usim_data.hplmn.plmn = network_records[SELECTED_PLMN].plmn; - usim_data.hplmn.AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - - /* - * List of user controlled PLMN selector with Access Technology - */ - for (int i = 0; i < USIM_PLMN_MAX; i++) { - memset(&usim_data.plmn[i], 0xff, sizeof(plmn_t)); - } - - /* - * List of operator controlled PLMN selector with Access Technology - */ - usim_data.oplmn[0].plmn = network_records[VDF1].plmn; - usim_data.oplmn[0].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - usim_data.oplmn[1].plmn = network_records[VDF2].plmn; - usim_data.oplmn[1].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - usim_data.oplmn[2].plmn = network_records[VDF3].plmn; - usim_data.oplmn[2].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - usim_data.oplmn[3].plmn = network_records[VDF4].plmn; - usim_data.oplmn[3].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - usim_data.oplmn[4].plmn = network_records[VDF5].plmn; - usim_data.oplmn[4].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN); - - for (int i = 5; i < USIM_OPLMN_MAX; i++) { - memset(&usim_data.oplmn[i], 0xff, sizeof(plmn_t)); - } - - /* - * EPS Location Information - */ - usim_data.epsloci.guti.gummei.plmn = network_records[SELECTED_PLMN].plmn; - usim_data.epsloci.guti.gummei.MMEgid = DEFAULT_MME_ID; - usim_data.epsloci.guti.gummei.MMEcode = DEFAULT_MME_CODE; - usim_data.epsloci.guti.m_tmsi = DEFAULT_M_TMSI; - usim_data.epsloci.tai.plmn = usim_data.epsloci.guti.gummei.plmn; - usim_data.epsloci.tai.tac = DEFAULT_TAC; - usim_data.epsloci.status = USIM_EPSLOCI_UPDATED; - /* - * Non-Access Stratum configuration - */ - usim_data.nasconfig.NAS_SignallingPriority.type = USIM_NAS_SIGNALLING_PRIORITY_TAG; - usim_data.nasconfig.NAS_SignallingPriority.length = 1; - usim_data.nasconfig.NAS_SignallingPriority.value[0] = 0x00; - usim_data.nasconfig.NMO_I_Behaviour.type = USIM_NMO_I_BEHAVIOUR_TAG; - usim_data.nasconfig.NMO_I_Behaviour.length = 1; - usim_data.nasconfig.NMO_I_Behaviour.value[0] = 0x00; - usim_data.nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG; - usim_data.nasconfig.AttachWithImsi.length = 1; -#if defined(START_WITH_GUTI) - usim_data.nasconfig.AttachWithImsi.value[0] = 0x00; -#else - usim_data.nasconfig.AttachWithImsi.value[0] = 0x01; -#endif - usim_data.nasconfig.MinimumPeriodicSearchTimer.type = USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG; - usim_data.nasconfig.MinimumPeriodicSearchTimer.length = 1; - usim_data.nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00; - usim_data.nasconfig.ExtendedAccessBarring.type = USIM_EXTENDED_ACCESS_BARRING_TAG; - usim_data.nasconfig.ExtendedAccessBarring.length = 1; - usim_data.nasconfig.ExtendedAccessBarring.value[0] = 0x00; - usim_data.nasconfig.Timer_T3245_Behaviour.type = USIM_TIMER_T3245_BEHAVIOUR_TAG; - usim_data.nasconfig.Timer_T3245_Behaviour.length = 1; - usim_data.nasconfig.Timer_T3245_Behaviour.value[0] = 0x00; - - /* - * Write USIM application data - */ - rc = usim_api_write(&usim_data); - - if (rc != RETURNok) { - perror("ERROR\t: usim_api_write() failed"); - exit(EXIT_FAILURE); - } - } - - /* - * Read USIM application data - */ - memset(&usim_data, 0, sizeof(usim_data_t)); - rc = usim_api_read(&usim_data); - - if (rc != RETURNok) { - perror("ERROR\t: usim_api_read() failed"); - exit(EXIT_FAILURE); - } - - /* - * Display USIM application data - */ - printf("\nUSIM data:\n\n"); - _display_usim_data(&usim_data); - - /* - * Display USIM file location - */ - char* path = memory_get_path("USIM_DIR", ".usim.nvram"); - printf("\nUSIM data file: %s\n", path); - free(path); - - exit(EXIT_SUCCESS); -} - -/****************************************************************************/ -/********************* L O C A L F U N C T I O N S *********************/ -/****************************************************************************/ - -/* - * Displays command line usage - */ -static void _display_usage(const char* command) -{ - fprintf(stderr, "usage: %s [OPTION]\n", command); - fprintf(stderr, "\t[--gen|-g]\tGenerate the USIM data file\n"); - fprintf(stderr, "\t[--print|-p]\tDisplay the content of the USIM data file\n"); - fprintf(stderr, "\t[--help|-h]\tDisplay this usage\n"); - const char* path = getenv("USIM_DIR"); - - if (path != NULL) { - fprintf(stderr, "USIM_DIR = %s\n", path); - } else { - fprintf(stderr, "USIM_DIR environment variable is not defined\n"); - } -} - -/* - * Displays USIM application data - */ -static void _display_usim_data(const usim_data_t* data) -{ - int digits; - - printf("Administrative Data:\n"); - printf("\tUE_Operation_Mode\t= 0x%.2x\n", data->ad.UE_Operation_Mode); - printf("\tAdditional_Info\t\t= 0x%.4x\n", data->ad.Additional_Info); - printf("\tMNC_Length\t\t= %d\n\n", data->ad.MNC_Length); - - printf("IMSI:\n"); - printf("\tlength\t= %d\n", data->imsi.length); - printf("\tparity\t= %s\n", data->imsi.u.num.parity == EVEN_PARITY ? "Even" : "Odd"); - digits = (data->imsi.length * 2) - 1 - (data->imsi.u.num.parity == EVEN_PARITY ? 1 : 0); - printf("\tdigits\t= %d\n", digits); - - printf("\tdigits\t= %u%u%u%u%u%x%u%u%u%u", - data->imsi.u.num.digit1, // MCC digit 1 - data->imsi.u.num.digit2, // MCC digit 2 - data->imsi.u.num.digit3, // MCC digit 3 - data->imsi.u.num.digit4, // MNC digit 1 - data->imsi.u.num.digit5, // MNC digit 2 - data->imsi.u.num.digit6==0xf?0:data->imsi.u.num.digit6, // MNC digit 3 - data->imsi.u.num.digit7, - data->imsi.u.num.digit8, - data->imsi.u.num.digit9, - data->imsi.u.num.digit10); - - if (digits >= 11) - printf("%x", data->imsi.u.num.digit11); - - if (digits >= 12) - printf("%x", data->imsi.u.num.digit12); - - if (digits >= 13) - printf("%x", data->imsi.u.num.digit13); - - if (digits >= 14) - printf("%x", data->imsi.u.num.digit14); - - if (digits >= 15) - printf("%x", data->imsi.u.num.digit15); - - printf("\n\n"); - - printf("Ciphering and Integrity Keys:\n"); - printf("\tKSI\t: 0x%.2x\n", data->keys.ksi); - char key[USIM_CK_SIZE + 1]; - key[USIM_CK_SIZE] = '\0'; - memcpy(key, data->keys.ck, USIM_CK_SIZE); - printf("\tCK\t: \"%s\"\n", key); - memcpy(key, data->keys.ik, USIM_IK_SIZE); - printf("\tIK\t: \"%s\"\n", key); - - printf("EPS NAS security context:\n"); - printf("\tKSIasme\t: 0x%.2x\n", data->securityctx.KSIasme.value[0]); - char kasme[USIM_K_ASME_SIZE + 1]; - kasme[USIM_K_ASME_SIZE] = '\0'; - memcpy(kasme, data->securityctx.Kasme.value, USIM_K_ASME_SIZE); - printf("\tKasme\t: \"%s\"\n", kasme); - printf("\tulNAScount\t: 0x%.8x\n", - *(uint32_t*)data->securityctx.ulNAScount.value); - printf("\tdlNAScount\t: 0x%.8x\n", - *(uint32_t*)data->securityctx.dlNAScount.value); - printf("\talgorithmID\t: 0x%.2x\n\n", - data->securityctx.algorithmID.value[0]); - - printf("MSISDN\t= %u%u%u %u%u%u%u %u%u%u%u\n\n", - data->msisdn.number.digit[0].msb, - data->msisdn.number.digit[0].lsb, - data->msisdn.number.digit[1].msb, - data->msisdn.number.digit[1].lsb, - data->msisdn.number.digit[2].msb, - data->msisdn.number.digit[2].lsb, - data->msisdn.number.digit[3].msb, - data->msisdn.number.digit[3].lsb, - data->msisdn.number.digit[4].msb, - data->msisdn.number.digit[4].lsb, - data->msisdn.number.digit[5].msb); - - for (int i = 0; i < USIM_PNN_MAX; i++) { - printf("PNN[%d]\t= {%s, %s}\n", i, - data->pnn[i].fullname.value, data->pnn[i].shortname.value); - } - - printf("\n"); - - for (int i = 0; i < USIM_OPL_MAX; i++) { - printf("OPL[%d]\t= ", i); - PRINT_PLMN(data->opl[i].plmn); - printf(", TAC = [%.4x - %.4x], record_id = %d\n", - data->opl[i].start, data->opl[i].end, data->opl[i].record_id); - } - - printf("\n"); - - printf("HPLMN\t\t= "); - PRINT_PLMN(data->hplmn.plmn); - printf(", AcT = 0x%x\n\n", data->hplmn.AcT); - - for (int i = 0; i < USIM_FPLMN_MAX; i++) { - printf("FPLMN[%d]\t= ", i); - PRINT_PLMN(data->fplmn[i]); - printf("\n"); - } - - printf("\n"); - - for (int i = 0; i < USIM_EHPLMN_MAX; i++) { - printf("EHPLMN[%d]\t= ", i); - PRINT_PLMN(data->ehplmn[i]); - printf("\n"); - } - - printf("\n"); - - for (int i = 0; i < USIM_PLMN_MAX; i++) { - printf("PLMN[%d]\t\t= ", i); - PRINT_PLMN(data->plmn[i].plmn); - printf(", AcTPLMN = 0x%x", data->plmn[i].AcT); - printf("\n"); - } - - printf("\n"); - - for (int i = 0; i < USIM_OPLMN_MAX; i++) { - printf("OPLMN[%d]\t= ", i); - PRINT_PLMN(data->oplmn[i].plmn); - printf(", AcTPLMN = 0x%x", data->oplmn[i].AcT); - printf("\n"); - } - - printf("\n"); - - printf("HPPLMN\t\t= 0x%.2x (%d minutes)\n\n", data->hpplmn, data->hpplmn); - - printf("LOCI:\n"); - printf("\tTMSI = 0x%.4x\n", data->loci.tmsi); - printf("\tLAI\t: PLMN = "); - PRINT_PLMN(data->loci.lai.plmn); - printf(", LAC = 0x%.2x\n", data->loci.lai.lac); - printf("\tstatus\t= %d\n\n", data->loci.status); - - printf("PSLOCI:\n"); - printf("\tP-TMSI = 0x%.4x\n", data->psloci.p_tmsi); - printf("\tsignature = 0x%x 0x%x 0x%x\n", - data->psloci.signature[0], - data->psloci.signature[1], - data->psloci.signature[2]); - printf("\tRAI\t: PLMN = "); - PRINT_PLMN(data->psloci.rai.plmn); - printf(", LAC = 0x%.2x, RAC = 0x%.1x\n", - data->psloci.rai.lac, data->psloci.rai.rac); - printf("\tstatus\t= %d\n\n", data->psloci.status); - - printf("EPSLOCI:\n"); - printf("\tGUTI\t: GUMMEI\t: (PLMN = "); - PRINT_PLMN(data->epsloci.guti.gummei.plmn); - printf(", MMEgid = 0x%.2x, MMEcode = 0x%.1x)", - data->epsloci.guti.gummei.MMEgid, - data->epsloci.guti.gummei.MMEcode); - printf(", M-TMSI = 0x%.4x\n", data->epsloci.guti.m_tmsi); - printf("\tTAI\t: PLMN = "); - PRINT_PLMN(data->epsloci.tai.plmn); - printf(", TAC = 0x%.2x\n", - data->epsloci.tai.tac); - printf("\tstatus\t= %d\n\n", data->epsloci.status); - - printf("NASCONFIG:\n"); - printf("\tNAS_SignallingPriority\t\t: 0x%.2x\n", - data->nasconfig.NAS_SignallingPriority.value[0]); - printf("\tNMO_I_Behaviour\t\t\t: 0x%.2x\n", - data->nasconfig.NMO_I_Behaviour.value[0]); - printf("\tAttachWithImsi\t\t\t: 0x%.2x\n", - data->nasconfig.AttachWithImsi.value[0]); - printf("\tMinimumPeriodicSearchTimer\t: 0x%.2x\n", - data->nasconfig.MinimumPeriodicSearchTimer.value[0]); - printf("\tExtendedAccessBarring\t\t: 0x%.2x\n", - data->nasconfig.ExtendedAccessBarring.value[0]); - printf("\tTimer_T3245_Behaviour\t\t: 0x%.2x\n", - data->nasconfig.Timer_T3245_Behaviour.value[0]); -} - diff --git a/openair3/NAS/UE/API/USER/Makefile b/openair3/NAS/UE/API/USER/Makefile deleted file mode 100644 index d5f4d6fffba2deb77a25a7739e06ac10e10b858e..0000000000000000000000000000000000000000 --- a/openair3/NAS/UE/API/USER/Makefile +++ /dev/null @@ -1,42 +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.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.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 -# */ - -ifndef PROJDIR -PROJDIR = $(PWD)/../../.. -INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(IESDIR) -I$(EMMMSGDIR) -I$(ESMMSGDIR) -endif - -include $(PROJDIR)/Makerules -include $(PROJDIR)/Makefile.inc - -all: $(OBJS) - -%.o: %.c Makefile - @echo Compiling $< - @$(CC) $(CFLAGS) -c $< -o $@ - -clean: - $(RM) $(OBJS) *.bak *~ - -depend: - makedepend -- ${CFLAGS} -- ${SRCS} - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/openair3/NAS/UE/API/USER/at_command.c b/openair3/NAS/UE/API/USER/at_command.c index 89793a55ae3bdb38ba1b61f5390678628ec053e8..8f40ba93c434f7f06e7765ff09774318db28f13e 100644 --- a/openair3/NAS/UE/API/USER/at_command.c +++ b/openair3/NAS/UE/API/USER/at_command.c @@ -54,6 +54,7 @@ Description Defines the ATtention (AT) command set supported by the NAS /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ +// FIXME Put this in .h extern int at_response_format_v1; extern int at_error_code_suppression_q1; extern at_error_format_t at_error_format; @@ -278,6 +279,7 @@ int at_command_decode(const char* buffer, int length, at_command_t* at_command) char* buf = strdup(buffer+2); char* cmd = strtok(buf, ";"); + // FIXME check overflow for (i=0; cmd && (rc != RETURNerror); i++) { rc = ParseString(cmd, &at_command[i]); cmd = strtok(NULL, ";"); diff --git a/openair3/NAS/UE/API/USER/at_error.c b/openair3/NAS/UE/API/USER/at_error.c index 443c6a3300c5b2f2e336906f1b43fc37e739c954..7548fb513effb3d502cac4ce593b1f55e7be55f1 100644 --- a/openair3/NAS/UE/API/USER/at_error.c +++ b/openair3/NAS/UE/API/USER/at_error.c @@ -49,6 +49,7 @@ Description Defines error codes returned when execution of AT command /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ +// FIXME put this in .h extern int at_response_format_v1; /* diff --git a/openair3/NAS/UE/API/USER/tst/Makefile b/openair3/NAS/UE/API/USER/tst/Makefile deleted file mode 100644 index 48681f31a515265263b44c36873018bfb7ed1dec..0000000000000000000000000000000000000000 --- a/openair3/NAS/UE/API/USER/tst/Makefile +++ /dev/null @@ -1,58 +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.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.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 -# */ - -ifndef PROJDIR -PROJDIR = $(PWD)/../../../.. -endif - -include $(PROJDIR)/Makerules -include $(PROJDIR)/Makefile.inc - -LIBS = -lutil -lapi -lEMMmsg -lESMmsg -lies -INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(USERAPIDIR) - -LIBSAPI = $(LIBDIR)/$(LIBAPI).a $(LIBDIR)/$(LIBAPI).so - -TST_OBJ = at_parser.o - -TST_TARGET = at_parser - -TARGETS = $(TST_TARGET) - -all: $(TARGETS) - -%.o: %.c Makefile - $(CC) $(CFLAGS) -c $< -o $@ - -$(TST_TARGET): $(TST_OBJ) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) - -clean: - $(RM) $(OBJS) $(TARGETS) *.bak *~ - -depend: - makedepend -- ${CFLAGS} -- ${SRCS} - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -at_parser.o: $(USERAPIDIR)/at_command.h -at_parser.o: $(INCDIR)/commonDef.h $(INCDIR)/userDef.h -at_parser.o: $(INCDIR)/networkDef.h $(UTILDIR)/log.h diff --git a/openair3/NAS/UE/API/USER/user_api.c b/openair3/NAS/UE/API/USER/user_api.c index 9c2364629276e16338711ae481a8f9e601b7fe9d..a1300ea059d9dac26cfe107c3c6d9c0e02fc4f38 100644 --- a/openair3/NAS/UE/API/USER/user_api.c +++ b/openair3/NAS/UE/API/USER/user_api.c @@ -45,9 +45,9 @@ Description Implements the API used by the NAS layer running in the UE #include "device.h" #include "nas_user.h" -#include "at_command.h" #include "at_response.h" #include "at_error.h" +#include "esm_ebr.h" #include "user_indication.h" @@ -68,63 +68,12 @@ Description Implements the API used by the NAS layer running in the UE /* * Asynchronous notification procedure handlers */ -static int _user_api_registration_handler(unsigned char id, const void* data, size_t size); -static int _user_api_location_handler(unsigned char id, const void* data, size_t size); -static int _user_api_network_handler(unsigned char id, const void* data, size_t size); -static int _user_api_pdn_connection_handler(unsigned char id, const void* data, size_t size); - -static int _user_api_send(at_response_t* data); - -/* ------------------- - * Connection endpoint - * ------------------- - * The connection endpoint is used to send/receive data to/from the - * user application layer. Its definition depends on the underlaying - * mechanism chosen to communicate (network socket, I/O terminal device). - * A connection endpoint is handled using an identifier, and functions - * used to retreive the file descriptor actually allocated by the system, - * to receive data, to send data, and to perform clean up when connection - * is shut down. - * Only one single end to end connection with the user is managed at a - * time. - */ -static struct { - /* Connection endpoint reference */ - void* endpoint; - /* Connection endpoint handlers */ - void* (*open) (int, const char*, const char*); - int (*getfd)(const void*); - ssize_t (*recv) (void*, char*, size_t); - ssize_t (*send) (const void*, const char*, size_t); - void (*close)(void*); -} _user_api_id; - -#define USER_API_OPEN(a, b, c) _user_api_id.open(a, b, c) -#define USER_API_GETFD() _user_api_id.getfd(_user_api_id.endpoint) -#define USER_API_RECV(a, b) _user_api_id.recv(_user_api_id.endpoint, a, b) -#define USER_API_SEND(a, b) _user_api_id.send(_user_api_id.endpoint, a, b) -#define USER_API_CLOSE() _user_api_id.close(_user_api_id.endpoint) +static int _user_api_registration_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size); +static int _user_api_location_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size); +static int _user_api_network_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size); +static int _user_api_pdn_connection_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size); -/* - * The buffer used to receive data from the user application layer - */ -#define USER_API_RECV_BUFFER_SIZE 4096 -static char _user_api_recv_buffer[USER_API_RECV_BUFFER_SIZE]; - -/* - * The buffer used to send data to the user application layer - */ -#define USER_API_SEND_BUFFER_SIZE USER_API_RECV_BUFFER_SIZE -static char _user_api_send_buffer[USER_API_SEND_BUFFER_SIZE]; - -/* - * The decoded data received from the user application layer - */ -static struct { - int n_cmd; /* number of user data to be processed */ -#define USER_DATA_MAX 10 - at_command_t cmd[USER_DATA_MAX]; /* user data to be processed */ -} _user_data = {}; +static int _user_api_send(user_api_id_t *user_api_id, at_response_t* data); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -147,44 +96,44 @@ static struct { ** Others: _user_api_id ** ** ** ***************************************************************************/ -int user_api_initialize(const char* host, const char* port, +int user_api_initialize(user_api_id_t *user_api_id, const char* host, const char* port, const char* devname, const char* devparams) { LOG_FUNC_IN; - gethostname(_user_api_send_buffer, USER_API_SEND_BUFFER_SIZE); + gethostname(user_api_id->send_buffer, USER_API_SEND_BUFFER_SIZE); if (devname != NULL) { /* Initialize device handlers */ - _user_api_id.open = device_open; - _user_api_id.getfd = device_get_fd; - _user_api_id.recv = device_read; - _user_api_id.send = device_write; - _user_api_id.close = device_close; + user_api_id->open = device_open; + user_api_id->getfd = device_get_fd; + user_api_id->recv = device_read; + user_api_id->send = device_write; + user_api_id->close = device_close; /* Initialize communication channel */ - _user_api_id.endpoint = USER_API_OPEN(DEVICE, devname, devparams); + user_api_id->endpoint = user_api_id->open(DEVICE, devname, devparams); - if (_user_api_id.endpoint == NULL) { + if (user_api_id->endpoint == NULL) { LOG_TRACE(ERROR, "USR-API - Failed to open connection endpoint, " "%s", strerror(errno)); LOG_FUNC_RETURN (RETURNerror); } LOG_TRACE(INFO, "USR-API - User's communication device %d is OPENED " - "on %s/%s", user_api_get_fd(), _user_api_send_buffer, devname); + "on %s/%s", user_api_get_fd(user_api_id), user_api_id->send_buffer, devname); } else { /* Initialize network socket handlers */ - _user_api_id.open = socket_udp_open; - _user_api_id.getfd = socket_get_fd; - _user_api_id.recv = socket_recv; - _user_api_id.send = socket_send; - _user_api_id.close = socket_close; + user_api_id->open = socket_udp_open; + user_api_id->getfd = socket_get_fd; + user_api_id->recv = socket_recv; + user_api_id->send = socket_send; + user_api_id->close = socket_close; /* Initialize communication channel */ - _user_api_id.endpoint = USER_API_OPEN(SOCKET_SERVER, host, port); + user_api_id->endpoint = user_api_id->open(SOCKET_SERVER, host, port); - if (_user_api_id.endpoint == NULL) { + if (user_api_id->endpoint == NULL) { const char* error = ( (errno < 0) ? gai_strerror(errno) : strerror(errno) ); LOG_TRACE(ERROR, "USR-API - Failed to open connection endpoint, " @@ -193,7 +142,7 @@ int user_api_initialize(const char* host, const char* port, } LOG_TRACE(INFO, "USR-API - User's UDP socket %d is BOUND to %s/%s", - user_api_get_fd(), _user_api_send_buffer, port); + user_api_get_fd(user_api_id), user_api_id->send_buffer, port); } /* Register the asynchronous notification handlers */ @@ -238,10 +187,10 @@ int user_api_initialize(const char* host, const char* port, ** Others: None ** ** ** ***************************************************************************/ -int user_api_get_fd(void) +int user_api_get_fd(user_api_id_t *user_api_id) { LOG_FUNC_IN; - LOG_FUNC_RETURN (USER_API_GETFD()); + LOG_FUNC_RETURN (user_api_id->getfd(user_api_id->endpoint)); } /**************************************************************************** @@ -253,19 +202,18 @@ int user_api_get_fd(void) ** before its usage. ** ** ** ** Inputs: index: Index of the user data structure to get ** - ** Others: _user_data ** ** ** ** Outputs: Return: A generic pointer to the user data ** ** structure ** ** Others: None ** ** ** ***************************************************************************/ -const void* user_api_get_data(int index) +const void* user_api_get_data(user_at_commands_t *commands, int index) { LOG_FUNC_IN; - if (index < _user_data.n_cmd) { - LOG_FUNC_RETURN ((void*)(&_user_data.cmd[index])); + if (index < commands->n_cmd) { + LOG_FUNC_RETURN ((void*)(&commands->cmd[index])); } LOG_FUNC_RETURN (NULL); @@ -277,33 +225,23 @@ const void* user_api_get_data(int index) ** ** ** Description: Read data received from the user application layer ** ** ** - ** Inputs: fd: File descriptor of the connection endpoint ** - ** from which data have been received ** ** Others: _user_api_id ** ** ** ** Outputs: Return: The number of bytes read when success; ** ** RETURNerror Otherwise ** - ** Others: _user_api_recv_buffer, _user_api_id ** + ** Others: user_api_id->recv_buffer, _user_api_id ** ** ** ***************************************************************************/ -int user_api_read_data(int fd) +int user_api_read_data(user_api_id_t *user_api_id) { LOG_FUNC_IN; int rbytes; - /* Sanity check */ - int sfd = user_api_get_fd(); - - if (fd != sfd) { - LOG_TRACE(ERROR, "USR-API - Endpoint %d is not the one created for communication with the user application layer (%d)", fd, sfd); - LOG_FUNC_RETURN (RETURNerror); - } - - memset(_user_api_recv_buffer, 0, USER_API_RECV_BUFFER_SIZE); + memset(user_api_id->recv_buffer, 0, USER_API_RECV_BUFFER_SIZE); /* Receive data from the user application layer */ - rbytes = USER_API_RECV(_user_api_recv_buffer, USER_API_RECV_BUFFER_SIZE); + rbytes = user_api_id->recv(user_api_id->endpoint, user_api_id->recv_buffer, USER_API_RECV_BUFFER_SIZE); if (rbytes == RETURNerror) { LOG_TRACE(ERROR, "USR-API - recv() failed, %s", strerror(errno)); @@ -313,7 +251,7 @@ int user_api_read_data(int fd) } else { LOG_TRACE(INFO, "USR-API - %d bytes received " "from the user application layer", rbytes); - LOG_DUMP(_user_api_recv_buffer, rbytes); + LOG_DUMP(user_api_id->recv_buffer, rbytes); } LOG_FUNC_RETURN (rbytes); @@ -329,45 +267,42 @@ int user_api_read_data(int fd) ** ** ** Outputs: Return: The number of bytes write when success; ** ** RETURNerror Otherwise ** - ** Others: _user_api_recv_buffer ** + ** Others: user_api_id->recv_buffer ** ** ** ***************************************************************************/ -int user_api_set_data(char *message) +int user_api_set_data(user_api_id_t *user_api_id, char *message) { LOG_FUNC_IN; int rbytes; - memset(_user_api_recv_buffer, 0, USER_API_RECV_BUFFER_SIZE); + memset(user_api_id->recv_buffer, 0, USER_API_RECV_BUFFER_SIZE); - strncpy(_user_api_recv_buffer, message, USER_API_RECV_BUFFER_SIZE); - rbytes = strlen(_user_api_recv_buffer); + strncpy(user_api_id->recv_buffer, message, USER_API_RECV_BUFFER_SIZE); + rbytes = strlen(user_api_id->recv_buffer); LOG_TRACE(INFO, "USR-API - %d bytes write", rbytes); - LOG_DUMP(_user_api_recv_buffer, rbytes); + LOG_DUMP(user_api_id->recv_buffer, rbytes); LOG_FUNC_RETURN (rbytes); } /**************************************************************************** ** ** - ** Name: user_api_send_data() ** +** Name: user_api_send_data() ** ** ** ** Description: Send data to the user application layer ** ** ** - ** Inputs: fd: File descriptor of the connection endpoint ** - ** to which data have to be sent ** ** length: Number of bytes to send ** - ** Others: _user_api_send_buffer, _user_api_id ** ** ** ** Outputs: Return: The number of bytes sent when success; ** ** RETURNerror Otherwise ** ** Others: None ** ** ** ***************************************************************************/ -static int _user_api_send_data(int length) +static int _user_api_send_data(user_api_id_t *user_api_id, int length) { - int sbytes = USER_API_SEND(_user_api_send_buffer, length); + int sbytes = user_api_id->send(user_api_id->endpoint, user_api_id->send_buffer, length); if (sbytes == RETURNerror) { LOG_TRACE(ERROR, "USR-API - send() failed, %s", strerror(errno)); @@ -377,28 +312,25 @@ static int _user_api_send_data(int length) } else { LOG_TRACE(INFO, "USR-API - %d bytes sent " "to the user application layer", sbytes); - LOG_DUMP(_user_api_send_buffer, sbytes); + LOG_DUMP(user_api_id->send_buffer, sbytes); } return sbytes; } -int user_api_send_data(int fd, int length) + +/**************************************************************************** + ** ** + ** Name: user_api_close() ** + ***************************************************************************/ + int user_api_send_data(user_api_id_t *user_api_id, int length) { LOG_FUNC_IN; - /* Sanity check */ - int sfd = user_api_get_fd(); - - if (fd != sfd) { - LOG_TRACE(ERROR, "USR-API - Endpoint %d is not the one created for communication with the user application layer (%d)", fd, sfd); - LOG_FUNC_RETURN (RETURNerror); - } - /* Send data to the user application layer */ int sbytes = 0; if (length > 0) { - sbytes = _user_api_send_data(length); + sbytes = _user_api_send_data(user_api_id, length); } LOG_FUNC_RETURN (sbytes); @@ -411,31 +343,18 @@ int user_api_send_data(int fd, int length) ** Description: Close the user API from which the NAS layer sent/received ** ** messages to/from the user application layer ** ** ** - ** Inputs: fd: File descriptor of the connection endpoint ** - ** allocated by the system to communicate ** - ** with the user application layer ** ** Others: None ** ** ** ** Outputs: Return: None ** - ** Others: _user_api_id ** ** ** ***************************************************************************/ -void user_api_close(int fd) +void user_api_close(user_api_id_t *user_api_id) { LOG_FUNC_IN; - /* Sanity check */ - int sfd = user_api_get_fd(); - - if (fd != sfd) { - LOG_TRACE(ERROR, "USR-API - Endpoint %d is not the one created for communication with the user application layer (%d)", fd, sfd); - LOG_FUNC_OUT; - return; - } - /* Cleanup the connection endpoint */ - USER_API_CLOSE(); - _user_api_id.endpoint = NULL; + user_api_id->close(user_api_id->endpoint) ; + user_api_id->endpoint = NULL; LOG_FUNC_OUT; } @@ -450,46 +369,45 @@ void user_api_close(int fd) ** layer when the AT command failed to be decoded. ** ** ** ** Inputs: length: Number of bytes to decode ** - ** Others: _user_api_recv_buffer ** ** ** ** Outputs: Return: The number of AT commands succeessfully ** ** decoded ** - ** Others: _user_api_send_buffer, _user_data ** ** ** ***************************************************************************/ -int user_api_decode_data(int length) +int user_api_decode_data(user_api_id_t *user_api_id, user_at_commands_t *commands, int length) { LOG_FUNC_IN; /* Parse the AT command line */ - LOG_TRACE(INFO, "USR-API - Decode user data: %s", _user_api_recv_buffer); - _user_data.n_cmd = at_command_decode(_user_api_recv_buffer, length, - _user_data.cmd); + LOG_TRACE(INFO, "USR-API - Decode user data: %s", user_api_id->recv_buffer); + commands->n_cmd = at_command_decode(user_api_id->recv_buffer, length, + commands->cmd); - if (_user_data.n_cmd > 0) { + if (commands->n_cmd > 0) { /* AT command data received from the user application layer * has been successfully decoded */ LOG_TRACE(INFO, "USR-API - %d AT command%s ha%s been successfully " - "decoded", _user_data.n_cmd, - (_user_data.n_cmd > 1) ? "s" : "", - (_user_data.n_cmd > 1) ? "ve" : "s"); + "decoded", commands->n_cmd, + (commands->n_cmd > 1) ? "s" : "", + (commands->n_cmd > 1) ? "ve" : "s"); } else { int bytes; /* Failed to decode AT command data received from the user * application layer; Return syntax error code message */ LOG_TRACE(ERROR, "USR-API - Syntax error: Failed to decode " - "AT command data %s", _user_api_recv_buffer); + "AT command data %s", user_api_id->recv_buffer); /* Encode the syntax error code message */ - bytes = at_error_encode(_user_api_send_buffer, AT_ERROR_SYNTAX, + bytes = at_error_encode(user_api_id->send_buffer, AT_ERROR_SYNTAX, AT_ERROR_OPERATION_NOT_SUPPORTED); + // FIXME move _user_data call /* Send the syntax error code message */ - (void) _user_api_send_data(bytes); + _user_api_send_data(user_api_id, bytes); } - LOG_FUNC_RETURN (_user_data.n_cmd); + LOG_FUNC_RETURN (commands->n_cmd); } /**************************************************************************** @@ -508,10 +426,9 @@ int user_api_decode_data(int length) ** Outputs: Return: The number of characters that have been ** ** successfully encoded; ** ** RETURNerror otherwise. ** - ** Others: _user_api_send_buffer ** ** ** ***************************************************************************/ -int user_api_encode_data(const void* data, int success_code) +int user_api_encode_data(user_api_id_t *user_api_id, const void* data, int success_code) { LOG_FUNC_IN; @@ -520,16 +437,16 @@ int user_api_encode_data(const void* data, int success_code) /* Encode AT command error message */ if (user_data->cause_code != AT_ERROR_SUCCESS) { - bytes = at_error_encode(_user_api_send_buffer, AT_ERROR_CME, + bytes = at_error_encode(user_api_id->send_buffer, AT_ERROR_CME, user_data->cause_code); } /* Encode AT command response message */ else { - bytes = at_response_encode(_user_api_send_buffer, user_data); + bytes = at_response_encode(user_api_id->send_buffer, user_data); /* Add success result code */ if ( (success_code) && (bytes != RETURNerror) ) { - bytes += at_error_encode(&_user_api_send_buffer[bytes], + bytes += at_error_encode(&user_api_id->send_buffer[bytes], AT_ERROR_OK, 0); } } @@ -567,7 +484,7 @@ int user_api_encode_data(const void* data, int success_code) ** Others: None ** ** ** ***************************************************************************/ -int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, +int user_api_emm_callback(user_api_id_t *user_api_id, Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, const char* data, size_t size) { LOG_FUNC_IN; @@ -579,14 +496,14 @@ int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, * The list of available operators present in the network has to be * displayed to the user application */ - rc = user_ind_notify(USER_IND_PLMN, (void*)data, size); + rc = user_ind_notify(user_api_id, USER_IND_PLMN, (void*)data, size); } else { user_indication_t ind; ind.notification.reg.status = stat; if (size > 0) { /* The UE's network registration status has changed */ - rc = user_ind_notify(USER_IND_REG, (void*)&ind, 0); + rc = user_ind_notify(user_api_id, USER_IND_REG, (void*)&ind, 0); } if (rc != RETURNerror) { @@ -596,7 +513,7 @@ int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, ind.notification.loc.tac = tac; ind.notification.loc.ci = ci; ind.notification.loc.AcT = AcT; - rc = user_ind_notify(USER_IND_LOC, (void*)&ind, 0); + rc = user_ind_notify(user_api_id, USER_IND_LOC, (void*)&ind, 0); } } @@ -624,7 +541,7 @@ int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, ** Others: None ** ** ** ***************************************************************************/ -int user_api_esm_callback(int cid, network_pdn_state_t state) +int user_api_esm_callback(user_api_id_t *user_api_id, int cid, network_pdn_state_t state) { LOG_FUNC_IN; @@ -634,7 +551,7 @@ int user_api_esm_callback(int cid, network_pdn_state_t state) ind.notification.pdn.cid = cid; ind.notification.pdn.status = state; /* The status of the specified PDN connection has changed */ - rc = user_ind_notify(USER_IND_PDN, (void*)&ind, 0); + rc = user_ind_notify(user_api_id, USER_IND_PDN, (void*)&ind, 0); LOG_FUNC_RETURN (rc); } @@ -650,23 +567,22 @@ int user_api_esm_callback(int cid, network_pdn_state_t state) ** Description: Encodes and sends data to the user application layer ** ** ** ** Inputs: data: The data to send ** - ** Others: _user_api_send_buffer, _user_api_id ** ** ** ** Outputs: Return: The number of bytes sent when success; ** ** RETURNerror Otherwise ** ** Others: None ** ** ** ***************************************************************************/ -static int _user_api_send(at_response_t* data) +static int _user_api_send(user_api_id_t *user_api_id, at_response_t* data) { LOG_FUNC_IN; /* Encode AT command response message */ - int bytes = at_response_encode(_user_api_send_buffer, data); + int bytes = at_response_encode(user_api_id->send_buffer, data); /* Send the AT command response message to the user application */ if (bytes != RETURNerror) { - bytes = _user_api_send_data(bytes); + bytes = _user_api_send_data(user_api_id, bytes); } LOG_FUNC_RETURN (bytes); @@ -693,7 +609,7 @@ static int _user_api_send(at_response_t* data) ** Others: None ** ** ** ***************************************************************************/ -static int _user_api_registration_handler(unsigned char id, const void* data, +static int _user_api_registration_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size) { LOG_FUNC_IN; @@ -710,7 +626,7 @@ static int _user_api_registration_handler(unsigned char id, const void* data, at_response.response.cereg.stat = reg->status; /* Encode and send the AT command response message to the user */ - int bytes = _user_api_send(&at_response); + int bytes = _user_api_send(user_api_id, &at_response); LOG_FUNC_RETURN (bytes); } @@ -735,7 +651,7 @@ static int _user_api_registration_handler(unsigned char id, const void* data, ** Others: None ** ** ** ***************************************************************************/ -static int _user_api_location_handler(unsigned char id, const void* data, +static int _user_api_location_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size) { LOG_FUNC_IN; @@ -759,7 +675,7 @@ static int _user_api_location_handler(unsigned char id, const void* data, } /* Encode and send the AT command response message to the user */ - int bytes = _user_api_send(&at_response); + int bytes = _user_api_send(user_api_id, &at_response); LOG_FUNC_RETURN (bytes); } @@ -782,7 +698,7 @@ static int _user_api_location_handler(unsigned char id, const void* data, ** Others: None ** ** ** ***************************************************************************/ -static int _user_api_network_handler(unsigned char id, const void* data, +static int _user_api_network_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size) { LOG_FUNC_IN; @@ -795,7 +711,7 @@ static int _user_api_network_handler(unsigned char id, const void* data, at_response.response.cops.tst.size = size; /* Encode and send the AT command response message to the user */ - int bytes = _user_api_send(&at_response); + int bytes = _user_api_send(user_api_id, &at_response); LOG_FUNC_RETURN (bytes); } @@ -820,7 +736,7 @@ static int _user_api_network_handler(unsigned char id, const void* data, ** Others: None ** ** ** ***************************************************************************/ -static int _user_api_pdn_connection_handler(unsigned char id, const void* data, +static int _user_api_pdn_connection_handler(user_api_id_t *user_api_id, unsigned char id, const void* data, size_t size) { LOG_FUNC_IN; @@ -837,7 +753,7 @@ static int _user_api_pdn_connection_handler(unsigned char id, const void* data, at_response.response.cgev.code = pdn->status; /* Encode and send the AT command response message to the user */ - int bytes = _user_api_send(&at_response); + int bytes = _user_api_send(user_api_id, &at_response); LOG_FUNC_RETURN (bytes); } diff --git a/openair3/NAS/UE/API/USER/user_api.h b/openair3/NAS/UE/API/USER/user_api.h index 9597c0f1d1bbcedb1908abf4bde53cf9247fb2cd..6536144165b540bd9bf186d888aaf14c41eeb00b 100644 --- a/openair3/NAS/UE/API/USER/user_api.h +++ b/openair3/NAS/UE/API/USER/user_api.h @@ -42,15 +42,14 @@ Description Implements the API used by the NAS layer running in the UE #include "commonDef.h" #include "networkDef.h" +#include "at_command.h" +#include "user_api_defs.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ -/****************************************************************************/ -/************************ G L O B A L T Y P E S ************************/ -/****************************************************************************/ - /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ @@ -59,20 +58,20 @@ Description Implements the API used by the NAS layer running in the UE /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int user_api_initialize(const char* host, const char* port, const char* devname, const char* devparams); +int user_api_initialize(user_api_id_t *user_api_id, const char* host, const char* port, const char* devname, const char* devparams); -int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, const char* data, size_t size); -int user_api_esm_callback(int cid, network_pdn_state_t state); +int user_api_emm_callback(user_api_id_t *user_api_id, Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, const char* data, size_t size); +int user_api_esm_callback(user_api_id_t *user_api_id, int cid, network_pdn_state_t state); -int user_api_get_fd(void); -const void* user_api_get_data(int index); +int user_api_get_fd(user_api_id_t *user_api_id); +const void* user_api_get_data(user_at_commands_t *commands, int index); -int user_api_read_data(int fd); -int user_api_set_data(char *message); -int user_api_send_data(int fd, int length); -void user_api_close(int fd); +int user_api_read_data(user_api_id_t *user_api_id); +int user_api_set_data(user_api_id_t *user_api_id, char *message); +int user_api_send_data(user_api_id_t *user_api_id, int length); +void user_api_close(user_api_id_t *user_api_id); -int user_api_decode_data(int length); -int user_api_encode_data(const void* data, int add_success_code); +int user_api_decode_data(user_api_id_t *user_api_id, user_at_commands_t *commands, int length); +int user_api_encode_data(user_api_id_t *user_api_id, const void* data, int add_success_code); #endif /* __USER_API_H__ */ diff --git a/openair3/NAS/UE/API/USER/user_api_defs.h b/openair3/NAS/UE/API/USER/user_api_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..ef4d8cd383b93d49fad48011d87ac1531886578d --- /dev/null +++ b/openair3/NAS/UE/API/USER/user_api_defs.h @@ -0,0 +1,50 @@ +#ifndef _USER_API_DEFS_H +#define _USER_API_DEFS_H + +#include <sys/types.h> +#include "at_command.h" + +/****************************************************************************/ +/************************ G L O B A L T Y P E S ************************/ +/****************************************************************************/ + +#define USER_API_RECV_BUFFER_SIZE 4096 +#define USER_API_SEND_BUFFER_SIZE USER_API_RECV_BUFFER_SIZE +#define USER_DATA_MAX 10 + +/* + * The decoded data received from the user application layer + */ +typedef struct { + int n_cmd; /* number of user data to be processed */ + at_command_t cmd[USER_DATA_MAX]; /* user data to be processed */ +} user_at_commands_t; + +/* ------------------- + * Connection endpoint + * ------------------- + * The connection endpoint is used to send/receive data to/from the + * user application layer. Its definition depends on the underlaying + * mechanism chosen to communicate (network socket, I/O terminal device). + * A connection endpoint is handled using an identifier, and functions + * used to retreive the file descriptor actually allocated by the system, + * to receive data, to send data, and to perform clean up when connection + * is shut down. + * Only one single end to end connection with the user is managed at a + * time. + */ +typedef struct { + /* Connection endpoint reference */ + void* endpoint; + /* Connection endpoint handlers */ + void* (*open) (int, const char*, const char*); + int (*getfd)(const void*); + ssize_t (*recv) (void*, char*, size_t); + ssize_t (*send) (const void*, const char*, size_t); + void (*close)(void*); + char recv_buffer[USER_API_RECV_BUFFER_SIZE]; + char send_buffer[USER_API_SEND_BUFFER_SIZE]; +} user_api_id_t; + + +#endif diff --git a/openair3/NAS/UE/API/USER/user_indication.c b/openair3/NAS/UE/API/USER/user_indication.c index d7495f46e767ffbe61ad9cd9133163fc2f76d496..620596005df5d3fdd1513a85d947486d242d7ac8 100644 --- a/openair3/NAS/UE/API/USER/user_indication.c +++ b/openair3/NAS/UE/API/USER/user_indication.c @@ -146,7 +146,7 @@ int user_ind_deregister(user_ind_t ind) ** Others: None ** ** ** ***************************************************************************/ -int user_ind_notify(user_ind_t ind, const void* data, size_t size) +int user_ind_notify(user_api_id_t *user_api_id, user_ind_t ind, const void* data, size_t size) { LOG_FUNC_IN; @@ -158,7 +158,7 @@ int user_ind_notify(user_ind_t ind, const void* data, size_t size) user_ind_callback_t notify = _user_ind_handler.callback[ind]; if (notify != NULL) { - rc = (*notify)(_user_ind_handler.id, data, size); + rc = (*notify)(user_api_id, _user_ind_handler.id, data, size); } } else { /* Silently discard not registered notification */ diff --git a/openair3/NAS/UE/API/USER/user_indication.h b/openair3/NAS/UE/API/USER/user_indication.h index d31a8754e49dc7ca85834d0d3f566124fb1741fb..39aba424e7a755f88ce91b3980d405dd5f819cba 100644 --- a/openair3/NAS/UE/API/USER/user_indication.h +++ b/openair3/NAS/UE/API/USER/user_indication.h @@ -43,6 +43,7 @@ Description Defines functions which allow the user application to register #include "commonDef.h" #include "networkDef.h" +#include "user_api_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -101,7 +102,7 @@ typedef struct { /* * Type of procedure executed upon receiving registered notification */ -typedef int (*user_ind_callback_t) (unsigned char, const void*, size_t); +typedef int (*user_ind_callback_t) (user_api_id_t *user_api_id, unsigned char, const void*, size_t); /****************************************************************************/ /************************ G L O B A L T Y P E S ************************/ @@ -117,6 +118,6 @@ typedef int (*user_ind_callback_t) (unsigned char, const void*, size_t); int user_ind_register(user_ind_t ind, unsigned char id, user_ind_callback_t cb); int user_ind_deregister(user_ind_t ind); -int user_ind_notify(user_ind_t ind, const void* data, size_t size); +int user_ind_notify(user_api_id_t *user_api_id, user_ind_t ind, const void* data, size_t size); #endif /* __USER_IND_H__*/ diff --git a/openair3/NAS/UE/API/USIM/Makefile b/openair3/NAS/UE/API/USIM/Makefile deleted file mode 100644 index d5f4d6fffba2deb77a25a7739e06ac10e10b858e..0000000000000000000000000000000000000000 --- a/openair3/NAS/UE/API/USIM/Makefile +++ /dev/null @@ -1,42 +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.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.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 -# */ - -ifndef PROJDIR -PROJDIR = $(PWD)/../../.. -INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(IESDIR) -I$(EMMMSGDIR) -I$(ESMMSGDIR) -endif - -include $(PROJDIR)/Makerules -include $(PROJDIR)/Makefile.inc - -all: $(OBJS) - -%.o: %.c Makefile - @echo Compiling $< - @$(CC) $(CFLAGS) -c $< -o $@ - -clean: - $(RM) $(OBJS) *.bak *~ - -depend: - makedepend -- ${CFLAGS} -- ${SRCS} - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/openair3/NAS/UE/API/USIM/aka_functions.c b/openair3/NAS/UE/API/USIM/aka_functions.c index 415ba695f21b4812bcd4828e296ee201499e8aaa..4d8f4cd1d31b33370056cea6e4b9556319e5a369 100644 --- a/openair3/NAS/UE/API/USIM/aka_functions.c +++ b/openair3/NAS/UE/API/USIM/aka_functions.c @@ -39,26 +39,6 @@ #include "aka_functions.h" #include "nas_log.h" -/*--------- Operator Variant Algorithm Configuration Field --------*/ -/*------- Insert your value of OP here -------*/ -/* PFT OP used currently in HSS (OPENAIRHSS/auc/kdf.c) */ -#define OAI_LTEBOX - -#ifdef OAI_LTEBOX -//1006020f0a478bf6b699f15c062e42b3 -/*u8 OP[16] = {0xb3, 0x42, 0x2e, 0x06, 0x5c, 0xf1, 0x99, 0xb6, - 0xf6, 0x8b, 0x47, 0x0a, 0x0f, 0x02, 0x06, 0x10 - };*/ -u8 OP[16] = {0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6, - 0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 -}; -#else -u8 OP[16] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 - }; -#endif -/*------- Insert your value of OP here -------*/ - /*------------------------------------------------------------------- * Algorithm f1 *------------------------------------------------------------------- @@ -69,16 +49,14 @@ u8 OP[16] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, * *-----------------------------------------------------------------*/ void f1 ( u8 k_pP[16], u8 rand_pP[16], u8 sqn_pP[6], u8 amf_pP[2], - u8 mac_a_pP[8] ) + u8 mac_a_pP[8], const u8 op_c[16]) { - u8 op_c[16]; u8 temp[16]; u8 in1[16]; u8 out1[16]; u8 rijndaelInput[16]; u8 i; RijndaelKeySchedule( k_pP ); - ComputeOPc( op_c ); for (i=0; i<16; i++) rijndaelInput[i] = rand_pP[i] ^ op_c[i]; @@ -124,9 +102,8 @@ void f1 ( u8 k_pP[16], u8 rand_pP[16], u8 sqn_pP[6], u8 amf_pP[2], * *-----------------------------------------------------------------*/ void f2345 ( u8 k_pP[16], u8 rand_pP[16], - u8 res_pP[8], u8 ck_pP[16], u8 ik_pP[16], u8 ak_pP[6] ) + u8 res_pP[8], u8 ck_pP[16], u8 ik_pP[16], u8 ak_pP[6],const u8 op_c[16]) { - u8 op_c[16]; u8 temp[16]; u8 out[16]; u8 rijndaelInput[16]; @@ -142,7 +119,6 @@ void f2345 ( u8 k_pP[16], u8 rand_pP[16], rand_pP[8],rand_pP[9],rand_pP[10],rand_pP[11],rand_pP[12],rand_pP[13],rand_pP[14],rand_pP[15]); RijndaelKeySchedule( k_pP ); - ComputeOPc( op_c ); for (i=0; i<16; i++) rijndaelInput[i] = rand_pP[i] ^ op_c[i]; @@ -225,16 +201,14 @@ void f2345 ( u8 k_pP[16], u8 rand_pP[16], * *-----------------------------------------------------------------*/ void f1star( u8 k_pP[16], u8 rand_pP[16], u8 sqn_pP[6], u8 amf_pP[2], - u8 mac_s_pP[8] ) + u8 mac_s_pP[8],const u8 op_c[16]) { - u8 op_c[16]; u8 temp[16]; u8 in1[16]; u8 out1[16]; u8 rijndaelInput[16]; u8 i; RijndaelKeySchedule( k_pP ); - ComputeOPc( op_c ); for (i=0; i<16; i++) rijndaelInput[i] = rand_pP[i] ^ op_c[i]; @@ -280,15 +254,13 @@ void f1star( u8 k_pP[16], u8 rand_pP[16], u8 sqn_pP[6], u8 amf_pP[2], * *-----------------------------------------------------------------*/ void f5star( u8 k_pP[16], u8 rand_pP[16], - u8 ak_pP[6] ) + u8 ak_pP[6], const u8 op_c[16]) { - u8 op_c[16]; u8 temp[16]; u8 out[16]; u8 rijndaelInput[16]; u8 i; RijndaelKeySchedule( k_pP ); - ComputeOPc( op_c ); for (i=0; i<16; i++) rijndaelInput[i] = rand_pP[i] ^ op_c[i]; @@ -316,22 +288,17 @@ void f5star( u8 k_pP[16], u8 rand_pP[16], * Function to compute OPc from OP and K. Assumes key schedule has already been performed. *-----------------------------------------------------------------*/ -void ComputeOPc( u8 op_c_pP[16] ) +void ComputeOPc(const u8 op[16], u8 op_c_pP[16]) { u8 i; LOG_TRACE(DEBUG, - "USIM-API - ComputeOPc : OP[0..15]=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", - OP[0],OP[1],OP[2], OP[3], OP[4], OP[5], OP[6], OP[7], - OP[8],OP[9],OP[10],OP[11],OP[12],OP[13],OP[14],OP[15]); - RijndaelEncrypt( OP, op_c_pP ); + "USIM-API - ComputeOPc : op[0..15]=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + op[0],op[1],op[2], op[3], op[4], op[5], op[6], op[7], + op[8],op[9],op[10],op[11],op[12],op[13],op[14],op[15]); + RijndaelEncrypt( op, op_c_pP ); for (i=0; i<16; i++) - op_c_pP[i] ^= OP[i]; - LOG_TRACE(DEBUG, - "USIM-API - OPc[0..15]=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", - op_c_pP[0],op_c_pP[1],op_c_pP[2], op_c_pP[3], op_c_pP[4], op_c_pP[5], op_c_pP[6], op_c_pP[7], - op_c_pP[8],op_c_pP[9],op_c_pP[10],op_c_pP[11],op_c_pP[12],op_c_pP[13],op_c_pP[14],op_c_pP[15]); - + op_c_pP[i] ^= op[i]; return; } /* end of function ComputeOPc */ @@ -489,7 +456,7 @@ void MixColumn(u8 state[4][4]) * 16-byte output (using round keys already derived from 16-byte * key). *-----------------------------------------------------------------*/ -void RijndaelEncrypt( u8 input[16], u8 output[16] ) +void RijndaelEncrypt(const u8 input[16], u8 output[16] ) { u8 state[4][4]; int i, r; diff --git a/openair3/NAS/UE/API/USIM/aka_functions.h b/openair3/NAS/UE/API/USIM/aka_functions.h index 66b5a90fbca6c356f057a733b4b5a2d72db7b43e..8c370bb76c8df239839cf6ab7f810495418301a7 100644 --- a/openair3/NAS/UE/API/USIM/aka_functions.h +++ b/openair3/NAS/UE/API/USIM/aka_functions.h @@ -23,13 +23,13 @@ typedef unsigned char u8; /*--------------------------- prototypes --------------------------*/ void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2], - u8 mac_a[8] ); + u8 mac_a[8], const u8 op[16]); void f2345 ( u8 k[16], u8 rand[16], - u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6] ); + u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6], const u8 op[16]); void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2], - u8 mac_s[8] ); + u8 mac_s[8], const u8 op[16]); void f5star( u8 k[16], u8 rand[16], - u8 ak[6] ); -void ComputeOPc( u8 op_c[16] ); + u8 ak[6], const u8 op[16]); +void ComputeOPc(const u8 op[16], u8 op_c_pP[16] ); void RijndaelKeySchedule( u8 key[16] ); -void RijndaelEncrypt( u8 input[16], u8 output[16] ); +void RijndaelEncrypt(const u8 input[16], u8 output[16] ); diff --git a/openair3/NAS/UE/API/USIM/usim_api.c b/openair3/NAS/UE/API/USIM/usim_api.c index 58ca9aa279e95e66375647e3760bf490f833dded..efb0383596dfc885bf20137c2673c25aa48909ea 100644 --- a/openair3/NAS/UE/API/USIM/usim_api.c +++ b/openair3/NAS/UE/API/USIM/usim_api.c @@ -41,11 +41,13 @@ Description Implements the API used by the NAS layer to read/write #include "usim_api.h" #include "nas_log.h" +#include "utils.h" #include "memory.h" #include <stdio.h> #include "aka_functions.h" #include <string.h> // memcpy, memset #include <stdlib.h> // malloc, free +#include <stdio.h> /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ @@ -55,46 +57,6 @@ Description Implements the API used by the NAS layer to read/write /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ -/* - * The name of the file where are stored data of the USIM application - */ -#define USIM_API_NVRAM_FILENAME ".usim.nvram" - -/* - * The name of the environment variable which defines the directory - * where the USIM application file is located - */ -#define USIM_API_NVRAM_DIRNAME "USIM_DIR" - -/* - * Subscriber authentication security key - */ -#define USIM_API_K_SIZE 16 -//#define USIM_API_K_VALUE "fec86ba6eb707ed08905757b1bb44b8f" -#define USIM_API_K_VALUE "8BAF473F2F8FD09487CCCBD7097C6862" -#define TEST_USIM_API_K_VALUE "000102030405060708090a0b0c0d0e0f" // CMW500 K key - -static uint8_t _usim_api_k[USIM_API_K_SIZE]; - - -/* - * List of last used Sequence Numbers SQN - */ -#define USIM_API_AK_SIZE 6 -#define USIM_API_SQN_SIZE USIM_API_AK_SIZE -#define USIM_API_SQNMS_SIZE USIM_API_SQN_SIZE - -static struct _usim_api_data_s { - /* Highest sequence number the USIM has ever accepted */ - uint8_t sqn_ms[USIM_API_SQNMS_SIZE]; - /* List of the last used sequence numbers */ -#define USIM_API_SQN_LIST_SIZE 32 - uint8_t n_sqns; - uint32_t sqn[USIM_API_SQN_LIST_SIZE]; -} _usim_api_data; - -static uint8_t _usim_api_hex_char_to_hex_value (char c); -static void _usim_api_hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size); static int _usim_api_check_sqn(uint32_t seq, uint8_t ind); /****************************************************************************/ @@ -115,38 +77,17 @@ static int _usim_api_check_sqn(uint32_t seq, uint8_t ind); ** Others: None ** ** ** ***************************************************************************/ -int usim_api_read(usim_data_t* data) +int usim_api_read(const char *filename, usim_data_t* data) { LOG_FUNC_IN; - /* Get USIM application pathname */ - char* path = memory_get_path(USIM_API_NVRAM_DIRNAME, - USIM_API_NVRAM_FILENAME); - - if (path == NULL) { - LOG_TRACE(ERROR, "USIM-API - Failed to get USIM pathname"); - LOG_FUNC_RETURN (RETURNerror); - } - /* Read USIM application data */ - if (memory_read(path, data, sizeof(usim_data_t)) != RETURNok) { + if (memory_read(filename, data, sizeof(usim_data_t)) != RETURNok) { LOG_TRACE(ERROR, "USIM-API - %s file is either not valid " - "or not present", path); - free(path); + "or not present", filename); LOG_FUNC_RETURN (RETURNerror); } - /* initialize the subscriber authentication security key */ - if(data->usimtestmode == 0) - { - _usim_api_hex_string_to_hex_value(_usim_api_k, USIM_API_K_VALUE, USIM_API_K_SIZE); - } - else - { - _usim_api_hex_string_to_hex_value(_usim_api_k, TEST_USIM_API_K_VALUE, USIM_API_K_SIZE); - } - - free(path); LOG_FUNC_RETURN (RETURNok); } @@ -164,28 +105,17 @@ int usim_api_read(usim_data_t* data) ** Others: None ** ** ** ***************************************************************************/ -int usim_api_write(const usim_data_t* data) +int usim_api_write(const char *filename, const usim_data_t* data) { LOG_FUNC_IN; - /* Get USIM application pathname */ - char* path = memory_get_path(USIM_API_NVRAM_DIRNAME, - USIM_API_NVRAM_FILENAME); - - if (path == NULL) { - LOG_TRACE(ERROR, "USIM-API - Failed to get USIM pathname"); - LOG_FUNC_RETURN (RETURNerror); - } - /* Write USIM application data */ - if (memory_write(path, data, sizeof(usim_data_t)) != RETURNok) { + if (memory_write(filename, data, sizeof(usim_data_t)) != RETURNok) { - LOG_TRACE(ERROR, "USIM-API - Unable to write USIM file %s", path); - free(path); + LOG_TRACE(ERROR, "USIM-API - Unable to write USIM file %s", filename); LOG_FUNC_RETURN (RETURNerror); } - free(path); LOG_FUNC_RETURN (RETURNok); } @@ -220,7 +150,8 @@ int usim_api_write(const usim_data_t* data) ** Others: None ** ** ** ***************************************************************************/ -int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* autn_pP, +int usim_api_authenticate_test(usim_data_t *usim_data, + const OctetString* rand_pP, const OctetString* autn_pP, OctetString* auts_pP, OctetString* res_pP, OctetString* ck_pP, OctetString* ik_pP) { @@ -236,7 +167,7 @@ int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* au // RES = XDOUT for (i=0; i<USIM_API_K_SIZE; i++) { - res_pP->value[i] = rand_pP->value[i] ^ _usim_api_k[i]; + res_pP->value[i] = rand_pP->value[i] ^ usim_data->keys.usim_api_k[i]; } //step2: res = f2(xdout,n) @@ -327,19 +258,19 @@ int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* au /* Concealed value of the counter SQNms in the USIM: * Conc(SQNMS) = SQNMS ⊕ f5*K(RAND) */ - f5star(_usim_api_k, rand_pP->value, ak); + f5star(usim_data->keys.usim_api_k, rand_pP->value, ak, usim_data->keys.opc); u8 sqn_ms[USIM_API_SQNMS_SIZE]; memset(sqn_ms, 0, USIM_API_SQNMS_SIZE); //#define USIM_API_SQN_MS_SIZE 3 - printf("_usim_api_data.sqn_ms %p\n",_usim_api_data.sqn_ms); + printf("usim_data->usim_sqn_data.sqn_ms %p\n", usim_data->usim_sqn_data.sqn_ms); for (i = 0; i < USIM_API_SQNMS_SIZE; i++) { //#warning "LG:BUG HERE TODO" - printf("i %d: ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i] %d\n",i, ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]); + printf("i %d: ((uint8_t*)(usim_data->usim_sqn_data.sqn_ms))[USIM_API_SQNMS_SIZE - i] %d\n",i, ((uint8_t*)(usim_data->usim_sqn_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]); sqn_ms[USIM_API_SQNMS_SIZE - i] = - ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]; + ((uint8_t*)(usim_data->usim_sqn_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]; } u8 sqnms[USIM_API_SQNMS_SIZE]; @@ -355,8 +286,8 @@ int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* au * MACS = f1*K(SQNMS || RAND || AMF) */ #define USIM_API_MACS_SIZE USIM_API_XMAC_SIZE u8 macs[USIM_API_MACS_SIZE]; - f1star(_usim_api_k, rand_pP->value, sqn_ms, - &rand_pP->value[USIM_API_SQN_SIZE], macs); + f1star(usim_data->keys.usim_api_k, rand_pP->value, sqn_ms, + &rand_pP->value[USIM_API_SQN_SIZE], macs, usim_data->keys.opc); LOG_TRACE(DEBUG, "USIM-API - MACS %02X%02X%02X%02X%02X%02X%02X%02X", macs[0],macs[1],macs[2],macs[3], macs[4],macs[5],macs[6],macs[7]); @@ -392,7 +323,6 @@ int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* au ** autn_pP: Authentication token ** ** AUTN = (SQN xor AK) || AMF || MAC ** ** 48 16 64 bits ** - ** Others: Security key ** ** ** ** Outputs: auts_pP: Re-synchronization token ** ** res_pP: Authentication response ** @@ -403,7 +333,7 @@ int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* au ** Others: None ** ** ** ***************************************************************************/ -int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP, +int usim_api_authenticate(usim_data_t *usim_data, const OctetString* rand_pP, const OctetString* autn_pP, OctetString* auts_pP, OctetString* res_pP, OctetString* ck_pP, OctetString* ik_pP) { @@ -421,8 +351,8 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP /* Compute the anonymity key AK = f5K (RAND) */ u8 ak[USIM_API_AK_SIZE]; - f2345(_usim_api_k, rand_pP->value, - res_pP->value, ck_pP->value, ik_pP->value, ak); + f2345(usim_data->keys.usim_api_k, rand_pP->value, + res_pP->value, ck_pP->value, ik_pP->value, ak, usim_data->keys.opc); LOG_TRACE(INFO, "USIM-API - res(f2) :%s",dump_octet_string(res_pP)); LOG_TRACE(INFO, "USIM-API - ck(f3) :%s",dump_octet_string(ck_pP)); LOG_TRACE(INFO, "USIM-API - ik(f4) :%s",dump_octet_string(ik_pP)); @@ -443,7 +373,7 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP /* Compute XMAC = f1K (SQN || RAND || AMF) */ #define USIM_API_XMAC_SIZE 8 u8 xmac[USIM_API_XMAC_SIZE]; - f1(_usim_api_k, rand_pP->value, sqn, &autn_pP->value[USIM_API_SQN_SIZE], xmac); + f1(usim_data->keys.usim_api_k, rand_pP->value, sqn, &autn_pP->value[USIM_API_SQN_SIZE], xmac, usim_data->keys.opc); LOG_TRACE(DEBUG, "USIM-API - Computed XMAC %02X%02X%02X%02X%02X%02X%02X%02X", xmac[0],xmac[1],xmac[2],xmac[3], @@ -471,19 +401,19 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP /* Concealed value of the counter SQNms in the USIM: * Conc(SQNMS) = SQNMS ⊕ f5*K(RAND) */ - f5star(_usim_api_k, rand_pP->value, ak); + f5star(usim_data->keys.usim_api_k, rand_pP->value, ak, usim_data->keys.opc); u8 sqn_ms[USIM_API_SQNMS_SIZE]; memset(sqn_ms, 0, USIM_API_SQNMS_SIZE); //#define USIM_API_SQN_MS_SIZE 3 - printf("_usim_api_data.sqn_ms %p\n",_usim_api_data.sqn_ms); + printf("usim_data->usim_sqn.sqn_ms %p\n",usim_data->usim_sqn_data.sqn_ms); for (i = 0; i < USIM_API_SQNMS_SIZE; i++) { //#warning "LG:BUG HERE TODO" - printf("i %d: ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i] %d\n",i, ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]); + printf("i %d: ((uint8_t*)(usim_data->usim_sqn_data.sqn_ms))[USIM_API_SQNMS_SIZE - i] %d\n",i, ((uint8_t*)(usim_data->usim_sqn_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]); sqn_ms[USIM_API_SQNMS_SIZE - i] = - ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]; + ((uint8_t*)(usim_data->usim_sqn_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]; } u8 sqnms[USIM_API_SQNMS_SIZE]; @@ -499,8 +429,8 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP * MACS = f1*K(SQNMS || RAND || AMF) */ #define USIM_API_MACS_SIZE USIM_API_XMAC_SIZE u8 macs[USIM_API_MACS_SIZE]; - f1star(_usim_api_k, rand_pP->value, sqn_ms, - &rand_pP->value[USIM_API_SQN_SIZE], macs); + f1star(usim_data->keys.usim_api_k, rand_pP->value, sqn_ms, + &rand_pP->value[USIM_API_SQN_SIZE], macs, usim_data->keys.opc); LOG_TRACE(DEBUG, "USIM-API - MACS %02X%02X%02X%02X%02X%02X%02X%02X", macs[0],macs[1],macs[2],macs[3], macs[4],macs[5],macs[6],macs[7]); @@ -520,57 +450,6 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP /********************* L O C A L F U N C T I O N S *********************/ /****************************************************************************/ -/**************************************************************************** - ** ** - ** Name: _usim_api_hex_char_to_hex_value() ** - ** ** - ** Description: Converts an hexadecimal ASCII coded digit into its value. ** - ** ** - ** Inputs: c: A char holding the ASCII coded value ** - ** Others: None ** - ** ** - ** Outputs: None ** - ** Return: Converted value ** - ** Others: None ** - ** ** - ***************************************************************************/ -static uint8_t _usim_api_hex_char_to_hex_value (char c) -{ - if (c >= 'A') { - /* Remove case bit */ - c &= ~('a' ^ 'A'); - - return (c - 'A' + 10); - } else { - return (c - '0'); - } -} - -/**************************************************************************** - ** ** - ** Name: _usim_api_hex_string_to_hex_value() ** - ** ** - ** Description: Converts an hexadecimal ASCII coded string into its value.** - ** ** - ** Inputs: hex_value: A pointer to the location to store the ** - ** conversion result ** - ** size: The size of hex_value in bytes ** - ** Others: None ** - ** ** - ** Outputs: hex_value: Converted value ** - ** Return: None ** - ** Others: None ** - ** ** - ***************************************************************************/ -static void _usim_api_hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size) -{ - int i; - - for (i=0; i < size; i++) { - hex_value[i] = (_usim_api_hex_char_to_hex_value(hex_string[2 * i]) << 4) | _usim_api_hex_char_to_hex_value(hex_string[2 * i + 1]); - } -} - /**************************************************************************** ** ** ** Name: _usim_api_check_sqn() ** diff --git a/openair3/NAS/UE/API/USIM/usim_api.h b/openair3/NAS/UE/API/USIM/usim_api.h index 8cfaeb8aed67d14a0ca3cecde85eeba9433ce3d1..f2f80d610c5d0601be4baa837125f2d2bff6a8d5 100644 --- a/openair3/NAS/UE/API/USIM/usim_api.h +++ b/openair3/NAS/UE/API/USIM/usim_api.h @@ -48,6 +48,23 @@ Description Implements the API used by the NAS layer to read/write /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ +/* + * Subscriber authentication security key + */ +#define USIM_API_K_SIZE 16 +#define USIM_API_K_VALUE "fec86ba6eb707ed08905757b1bb44b8f" + +/* + * The name of the file where are stored data of the USIM application + */ +#define USIM_API_NVRAM_FILENAME ".usim.nvram" + +/* + * The name of the environment variable which defines the directory + * where the USIM application file is located + */ +#define USIM_API_NVRAM_DIRNAME "USIM_DIR" + /****************************************************************************/ /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ @@ -106,8 +123,27 @@ typedef struct { /* Integrity key */ #define USIM_IK_SIZE 16 Byte_t ik[USIM_IK_SIZE]; + uint8_t usim_api_k[USIM_API_K_SIZE]; + uint8_t opc[16]; } usim_keys_t; +/* + * List of last used Sequence Numbers SQN + */ +#define USIM_API_AK_SIZE 6 +#define USIM_API_SQN_SIZE USIM_API_AK_SIZE +#define USIM_API_SQNMS_SIZE USIM_API_SQN_SIZE + +typedef struct { + /* Highest sequence number the USIM has ever accepted */ + uint8_t sqn_ms[USIM_API_SQNMS_SIZE]; + /* List of the last used sequence numbers */ +#define USIM_API_SQN_LIST_SIZE 32 + uint8_t n_sqns; + uint32_t sqn[USIM_API_SQN_LIST_SIZE]; +} usim_sqn_data_t; + + /* * EPS NAS Security Context * ------------------------ @@ -329,6 +365,7 @@ typedef struct { usim_nasconfig_t nasconfig; /* usim test mode */ uint8_t usimtestmode; + usim_sqn_data_t usim_sqn_data; } usim_data_t; /****************************************************************************/ @@ -339,14 +376,15 @@ typedef struct { /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int usim_api_read(usim_data_t* data); +int usim_api_read(const char *filename, usim_data_t* data); -int usim_api_write(const usim_data_t* data); +int usim_api_write(const char *filename, const usim_data_t* data); -int usim_api_authenticate(const OctetString* rand, const OctetString* autn, +int usim_api_authenticate(usim_data_t *usim_data, const OctetString* rand_pP, const OctetString* autn_pP, OctetString* auts, OctetString* res, OctetString* ck, OctetString* ik); -int usim_api_authenticate_test(const OctetString* rand, const OctetString* autn, +int usim_api_authenticate_test(usim_data_t *usim_data, + const OctetString* rand, const OctetString* autn, OctetString* auts, OctetString* res, OctetString* ck, OctetString* ik); diff --git a/openair3/NAS/UE/EMM/Attach.c b/openair3/NAS/UE/EMM/Attach.c index 939c5b4afdd7796e58ab66b76372e446336674ff..c0c82b9b4ccf258567f414882fa368e513b1bcb9 100644 --- a/openair3/NAS/UE/EMM/Attach.c +++ b/openair3/NAS/UE/EMM/Attach.c @@ -59,6 +59,7 @@ Description Defines the attach related EMM procedure executed by the #include "nas_timer.h" #include "emmData.h" +#include "emm_timers.h" #include "emm_sap.h" #include "esm_sap.h" @@ -90,24 +91,12 @@ static const char *_emm_attach_type_str[] = { /* * Timer handlers */ -void *_emm_attach_t3410_handler(void *); -static void *_emm_attach_t3411_handler(void *); -static void *_emm_attach_t3402_handler(void *); +static void *_emm_attach_t3411_handler(void *args); /* * Abnormal case attach procedure */ -static void _emm_attach_abnormal_cases_bcd(emm_sap_t *); - -/* - * Internal data used for attach procedure - */ -static struct { -#define EMM_ATTACH_COUNTER_MAX 5 - unsigned int attempt_count; /* Counter used to limit the number of - * subsequently rejected attach attempts */ -} _emm_attach_data = {0}; - +static void _emm_attach_abnormal_cases_bcd(nas_user_t *user, emm_sap_t *); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -133,14 +122,14 @@ static struct { ** INITIATED. ** ** ** ** Inputs: type: Type of the requested attach ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: T3402, T3410, T3411 ** ** ** ***************************************************************************/ -int emm_proc_attach(emm_proc_attach_type_t type) +int emm_proc_attach(nas_user_t *user, emm_proc_attach_type_t type) { LOG_FUNC_IN; @@ -148,13 +137,14 @@ int emm_proc_attach(emm_proc_attach_type_t type) emm_as_establish_t *emm_as = &emm_sap.u.emm_as.u.establish; esm_sap_t esm_sap; int rc; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach type = %s (%d)", _emm_attach_type_str[type], type); /* Update the emergency bearer service indicator */ if (type == EMM_ATTACH_TYPE_EMERGENCY) { - _emm_data.is_emergency = TRUE; + user->emm_data->is_emergency = TRUE; } /* Setup initial NAS information message to transfer */ @@ -163,7 +153,7 @@ int emm_proc_attach(emm_proc_attach_type_t type) emm_as->type = type; /* Set the RRC connection establishment cause */ - if (_emm_data.is_emergency) { + if (user->emm_data->is_emergency) { emm_as->RRCcause = NET_ESTABLISH_CAUSE_EMERGENCY; emm_as->RRCtype = NET_ESTABLISH_TYPE_EMERGENCY_CALLS; } else { @@ -172,7 +162,7 @@ int emm_proc_attach(emm_proc_attach_type_t type) } /* Set the PLMN identifier of the selected PLMN */ - emm_as->plmnID = &_emm_data.splmn; + emm_as->plmnID = &user->emm_data->splmn; /* * Process the EPS mobile identity */ @@ -182,55 +172,55 @@ int emm_proc_attach(emm_proc_attach_type_t type) emm_as->UEid.imei = NULL; /* Check whether the UE is configured for "AttachWithIMSI" */ - if (_emm_data.AttachWithImsi) { + if (user->emm_data->AttachWithImsi) { /* Check whether the selected PLMN is neither the registered PLMN * nor in the list of equivalent PLMNs */ - if ( (!_emm_data.is_rplmn) && (!_emm_data.is_eplmn) ) { + if ( (!user->emm_data->is_rplmn) && (!user->emm_data->is_eplmn) ) { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI"); /* Include the IMSI */ - emm_as->UEid.imsi = _emm_data.imsi; + emm_as->UEid.imsi = user->emm_data->imsi; } else { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with NO IMSI, is registered PLMN %d, is equivalent PLMN %d", - _emm_data.is_rplmn, - _emm_data.is_eplmn); + user->emm_data->is_rplmn, + user->emm_data->is_eplmn); } - } else if (_emm_data.guti) { + } else if (user->emm_data->guti) { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with GUTI"); /* Include a valid GUTI and the last visited registered TAI */ - emm_as->UEid.guti = _emm_data.guti; - emm_as->UEid.tai = _emm_data.tai; - } else if (!_emm_data.is_emergency) { + emm_as->UEid.guti = user->emm_data->guti; + emm_as->UEid.tai = user->emm_data->tai; + } else if (!user->emm_data->is_emergency) { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is no emergency and no GUTI"); /* Include the IMSI if no valid GUTI is available */ - emm_as->UEid.imsi = _emm_data.imsi; + emm_as->UEid.imsi = user->emm_data->imsi; } else { /* The UE is attaching for emergency bearer services and * does not hold a valid GUTI */ - if (_emm_data.imsi) { + if (user->emm_data->imsi) { /* Include the IMSI if valid (USIM is present) */ LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is emergency and no GUTI"); - emm_as->UEid.imsi = _emm_data.imsi; + emm_as->UEid.imsi = user->emm_data->imsi; } else { LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is emergency and no GUTI and no IMSI"); /* Include the IMEI if the IMSI is not valid */ - emm_as->UEid.imei = _emm_data.imei; + emm_as->UEid.imei = user->emm_data->imei; } } /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_as->sctx, _emm_data.security, FALSE, FALSE); + emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, FALSE, FALSE); emm_as->ksi = EMM_AS_NO_KEY_AVAILABLE; - if (_emm_data.security) { - if (_emm_data.security->type != EMM_KSI_NOT_AVAILABLE) { - emm_as->ksi = _emm_data.security->eksi; + if (user->emm_data->security) { + if (user->emm_data->security->type != EMM_KSI_NOT_AVAILABLE) { + emm_as->ksi = user->emm_data->security->eksi; } - LOG_TRACE(INFO, "EMM-PROC - eps_encryption 0x%X", _emm_data.security->capability.eps_encryption); - LOG_TRACE(INFO, "EMM-PROC - eps_integrity 0x%X", _emm_data.security->capability.eps_integrity); - emm_as->encryption = _emm_data.security->capability.eps_encryption; - emm_as->integrity = _emm_data.security->capability.eps_integrity; + LOG_TRACE(INFO, "EMM-PROC - eps_encryption 0x%X", user->emm_data->security->capability.eps_encryption); + LOG_TRACE(INFO, "EMM-PROC - eps_integrity 0x%X", user->emm_data->security->capability.eps_integrity); + emm_as->encryption = user->emm_data->security->capability.eps_encryption; + emm_as->integrity = user->emm_data->security->capability.eps_integrity; } /* @@ -244,15 +234,15 @@ int emm_proc_attach(emm_proc_attach_type_t type) /* TODO: PDN type should be set according to the IP capability of the UE */ esm_sap.data.pdn_connect.pdn_type = NET_PDN_TYPE_IPV4; esm_sap.data.pdn_connect.apn = NULL; - esm_sap.data.pdn_connect.is_emergency = _emm_data.is_emergency; - rc = esm_sap_send(&esm_sap); + esm_sap.data.pdn_connect.is_emergency = user->emm_data->is_emergency; + rc = esm_sap_send(user, &esm_sap); if (rc != RETURNerror) { /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ - rc = emm_proc_lowerlayer_initialize(emm_proc_attach_request, + rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, emm_proc_attach_request, emm_proc_attach_failure, - emm_proc_attach_release, NULL); + emm_proc_attach_release, user); if (rc != RETURNok) { LOG_TRACE(WARNING, "Failed to initialize EMM procedure handler"); @@ -260,12 +250,12 @@ int emm_proc_attach(emm_proc_attach_type_t type) } /* Start T3410 timer */ - T3410.id = nas_timer_start(T3410.sec, _emm_attach_t3410_handler, NULL); + emm_timers->T3410.id = nas_timer_start(emm_timers->T3410.sec, emm_attach_t3410_handler, user); LOG_TRACE(INFO,"EMM-PROC - Timer T3410 (%d) expires in %ld seconds", - T3410.id, T3410.sec); + emm_timers->T3410.id, emm_timers->T3410.sec); /* Stop T3402 and T3411 timers if running */ - T3402.id = nas_timer_stop(T3402.id); - T3411.id = nas_timer_stop(T3411.id); + emm_timers->T3402.id = nas_timer_stop(emm_timers->T3402.id); + emm_timers->T3411.id = nas_timer_stop(emm_timers->T3411.id); /* * Notify EMM-AS SAP that a RRC connection establishment procedure @@ -276,7 +266,7 @@ int emm_proc_attach(emm_proc_attach_type_t type) /* Get the PDN connectivity request to transfer within the ESM * container of the initial attach request message */ emm_sap.u.emm_as.u.establish.NASmsg = esm_sap.send; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN(rc); @@ -301,7 +291,7 @@ int emm_proc_attach(emm_proc_attach_type_t type) int emm_proc_attach_request(void *args) { LOG_FUNC_IN; - + nas_user_t *user=args; emm_sap_t emm_sap; int rc; @@ -309,7 +299,7 @@ int emm_proc_attach_request(void *args) * Notify EMM that Attach Request has been sent to the network */ emm_sap.primitive = EMMREG_ATTACH_REQ; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -342,10 +332,10 @@ int emm_proc_attach_request(void *args) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data, T3412, T3402, T3423 ** + ** Others: user->emm_data-> T3412, T3402, T3423 ** ** ** ***************************************************************************/ -int emm_proc_attach_accept(long t3412, long t3402, long t3423, +int emm_proc_attach_accept(nas_user_t *user, long t3412, long t3402, long t3423, int n_tais, tai_t *tai, GUTI_t *guti, int n_eplmns, plmn_t *eplmn, const OctetString *esm_msg_pP) @@ -357,51 +347,52 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, int rc; int i; int j; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(INFO, "EMM-PROC - EPS attach accepted by the network"); /* Stop timer T3410 */ - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); - T3410.id = nas_timer_stop(T3410.id); + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", emm_timers->T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); /* Delete old TAI list and store the received TAI list */ - _emm_data.ltai.n_tais = n_tais; + user->emm_data->ltai.n_tais = n_tais; for (i = 0; (i < n_tais) && (i < EMM_DATA_TAI_MAX); i++) { - _emm_data.ltai.tai[i] = tai[i]; + user->emm_data->ltai.tai[i] = tai[i]; } /* Update periodic tracking area update timer value */ - T3412.sec = t3412; + emm_timers->T3412.sec = t3412; /* Update attach failure timer value */ if ( !(t3402 < 0) ) { - T3402.sec = t3402; + emm_timers->T3402.sec = t3402; } /* Update E-UTRAN deactivate ISR timer value */ if ( !(t3423 < 0) ) { - T3423.sec = t3423; + emm_timers->T3423.sec = t3423; } /* Delete old GUTI and store the new assigned GUTI if provided */ if (guti) { - *_emm_data.guti = *guti; + *user->emm_data->guti = *guti; } /* Update the stored list of equivalent PLMNs */ - _emm_data.nvdata.eplmn.n_plmns = 0; + user->emm_data->nvdata.eplmn.n_plmns = 0; if (n_eplmns > 0) { for (i = 0; (i < n_eplmns) && (i < EMM_DATA_EPLMN_MAX); i++) { int is_forbidden = FALSE; - if (!_emm_data.is_emergency) { + if (!user->emm_data->is_emergency) { /* If the attach procedure is not for emergency bearer * services, the UE shall remove from the list any PLMN * code that is already in the list of forbidden PLMNs */ - for (j = 0; j < _emm_data.fplmn.n_plmns; j++) { - if (PLMNS_ARE_EQUAL(eplmn[i], _emm_data.fplmn.plmn[j])) { + for (j = 0; j < user->emm_data->fplmn.n_plmns; j++) { + if (PLMNS_ARE_EQUAL(eplmn[i], user->emm_data->fplmn.plmn[j])) { is_forbidden = TRUE; break; } @@ -409,15 +400,15 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, } if ( !is_forbidden ) { - _emm_data.nvdata.eplmn.plmn[_emm_data.nvdata.eplmn.n_plmns++] = + user->emm_data->nvdata.eplmn.plmn[user->emm_data->nvdata.eplmn.n_plmns++] = eplmn[i]; } } /* Add the PLMN code of the registered PLMN that sent the list */ - if (_emm_data.nvdata.eplmn.n_plmns < EMM_DATA_EPLMN_MAX) { - _emm_data.nvdata.eplmn.plmn[_emm_data.nvdata.eplmn.n_plmns++] = - _emm_data.splmn; + if (user->emm_data->nvdata.eplmn.n_plmns < EMM_DATA_EPLMN_MAX) { + user->emm_data->nvdata.eplmn.plmn[user->emm_data->nvdata.eplmn.n_plmns++] = + user->emm_data->splmn; } } @@ -427,14 +418,14 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REQ; esm_sap.is_standalone = FALSE; esm_sap.recv = esm_msg_pP; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); if ( (rc != RETURNerror) && (esm_sap.err == ESM_SAP_SUCCESS) ) { /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ - rc = emm_proc_lowerlayer_initialize(emm_proc_attach_complete, + rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, emm_proc_attach_complete, emm_proc_attach_failure, - NULL, NULL); + NULL, user); if (rc != RETURNok) { LOG_TRACE(WARNING, @@ -448,17 +439,17 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, * be sent to the network */ emm_sap.primitive = EMMAS_DATA_REQ; - emm_sap.u.emm_as.u.data.guti = _emm_data.guti; - emm_sap.u.emm_as.u.data.ueid = 0; + emm_sap.u.emm_as.u.data.guti = user->emm_data->guti; + emm_sap.u.emm_as.u.data.ueid = user->ueid; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, - _emm_data.security, FALSE, TRUE); + user->emm_data->security, FALSE, TRUE); /* Get the activate default EPS bearer context accept message * to be transfered within the ESM container of the attach * complete message */ emm_sap.u.emm_as.u.data.NASinfo = EMM_AS_NAS_DATA_ATTACH; emm_sap.u.emm_as.u.data.NASmsg = esm_sap.send; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } else if (esm_sap.err != ESM_SAP_DISCARDED) { /* 3GPP TS 24.301, section 5.5.1.2.6, case j * If the ACTIVATE DEFAULT BEARER CONTEXT REQUEST message combined @@ -467,7 +458,7 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, * procedure by sending a DETACH REQUEST message to the network. */ emm_sap.primitive = EMMREG_DETACH_INIT; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } else { /* * ESM procedure failed and, received message has been discarded or @@ -497,22 +488,23 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data, _emm_attach_data, T3410 ** ** ** ***************************************************************************/ -int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) +int emm_proc_attach_reject(nas_user_t *user, int emm_cause, const OctetString *esm_msg_pP) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc; + emm_timers_t *emm_timers = user->emm_data->emm_timers; + emm_attach_data_t *emm_attach_data = user->emm_data->emm_attach_data; LOG_TRACE(WARNING, "EMM-PROC - EPS attach rejected by the network, " "EMM cause = %d", emm_cause); /* Stop timer T3410 */ - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); - T3410.id = nas_timer_stop(T3410.id); + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", emm_timers->T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); /* Update the EPS update status, the GUTI, the visited registered TAI and * the eKSI */ @@ -528,15 +520,15 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) case EMM_CAUSE_ROAMING_NOT_ALLOWED: case EMM_CAUSE_NO_SUITABLE_CELLS: /* Set the EPS update status to EU3 ROAMING NOT ALLOWED */ - _emm_data.status = EU3_ROAMING_NOT_ALLOWED; + user->emm_data->status = EU3_ROAMING_NOT_ALLOWED; /* Delete the GUTI */ - _emm_data.guti = NULL; + user->emm_data->guti = NULL; /* Delete the last visited registered TAI */ - _emm_data.tai = NULL; + user->emm_data->tai = NULL; /* Delete the eKSI */ - if (_emm_data.security) { - _emm_data.security->type = EMM_KSI_NOT_AVAILABLE; + if (user->emm_data->security) { + user->emm_data->security->type = EMM_KSI_NOT_AVAILABLE; } break; @@ -552,34 +544,34 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) case EMM_CAUSE_EPS_NOT_ALLOWED: case EMM_CAUSE_BOTH_NOT_ALLOWED: /* Consider the USIM as invalid for EPS services */ - _emm_data.usim_is_valid = FALSE; + user->emm_data->usim_is_valid = FALSE; /* Delete the list of equivalent PLMNs */ - _emm_data.nvdata.eplmn.n_plmns = 0; + user->emm_data->nvdata.eplmn.n_plmns = 0; break; case EMM_CAUSE_PLMN_NOT_ALLOWED: case EMM_CAUSE_NOT_AUTHORIZED_IN_PLMN: case EMM_CAUSE_ROAMING_NOT_ALLOWED: /* Delete the list of equivalent PLMNs */ - _emm_data.nvdata.eplmn.n_plmns = 0; + user->emm_data->nvdata.eplmn.n_plmns = 0; /* Reset the attach attempt counter */ - _emm_attach_data.attempt_count = 0; + emm_attach_data->attempt_count = 0; break; case EMM_CAUSE_TA_NOT_ALLOWED: case EMM_CAUSE_EPS_NOT_ALLOWED_IN_PLMN: case EMM_CAUSE_NO_SUITABLE_CELLS: /* Reset the attach attempt counter */ - _emm_attach_data.attempt_count = 0; + emm_attach_data->attempt_count = 0; break; case EMM_CAUSE_ESM_FAILURE: /* 3GPP TS 24.301, section 5.5.1.2.6, case d */ - if (_emm_data.NAS_SignallingPriority != 1) { + if (user->emm_data->NAS_SignallingPriority != 1) { /* The UE is not configured for NAS signalling low priority; * set the attach attempt counter to 5 */ - _emm_attach_data.attempt_count = EMM_ATTACH_COUNTER_MAX; + emm_attach_data->attempt_count = EMM_ATTACH_COUNTER_MAX; } break; @@ -591,7 +583,7 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) case EMM_CAUSE_PROTOCOL_ERROR: /* 3GPP TS 24.301, section 5.5.1.2.6, case d * Set the attach attempt counter to 5 */ - _emm_attach_data.attempt_count = EMM_ATTACH_COUNTER_MAX; + emm_attach_data->attempt_count = EMM_ATTACH_COUNTER_MAX; break; default : @@ -603,25 +595,25 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) case EMM_CAUSE_PLMN_NOT_ALLOWED: case EMM_CAUSE_NOT_AUTHORIZED_IN_PLMN: /* Store the PLMN identity in the "forbidden PLMN list" */ - _emm_data.fplmn.plmn[_emm_data.fplmn.n_plmns++] = _emm_data.splmn; + user->emm_data->fplmn.plmn[user->emm_data->fplmn.n_plmns++] = user->emm_data->splmn; break; case EMM_CAUSE_TA_NOT_ALLOWED: /* Store the current TAI in the list of "forbidden tracking * areas for regional provision of service" */ - _emm_data.ftai.tai[_emm_data.ftai.n_tais++] = *_emm_data.tai; + user->emm_data->ftai.tai[user->emm_data->ftai.n_tais++] = *user->emm_data->tai; break; case EMM_CAUSE_ROAMING_NOT_ALLOWED: /* Store the current TAI in the list of "forbidden tracking * areas for roaming" */ - _emm_data.ftai_roaming.tai[_emm_data.ftai_roaming.n_tais++] = *_emm_data.tai; + user->emm_data->ftai_roaming.tai[user->emm_data->ftai_roaming.n_tais++] = *user->emm_data->tai; break; case EMM_CAUSE_EPS_NOT_ALLOWED_IN_PLMN: /* Store the PLMN identity in the "forbidden PLMNs for GPRS * service" list */ - _emm_data.fplmn_gprs.plmn[_emm_data.fplmn_gprs.n_plmns++] = _emm_data.splmn; + user->emm_data->fplmn_gprs.plmn[user->emm_data->fplmn_gprs.n_plmns++] = user->emm_data->splmn; break; default : @@ -662,7 +654,7 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) break; case EMM_CAUSE_IMEI_NOT_ACCEPTED: - if (_emm_data.is_emergency) { + if (user->emm_data->is_emergency) { /* * Notify EMM that the UE failed to register to the network * for emergency bearer services because "IMEI not accepted" @@ -676,11 +668,11 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) default : /* Other values are considered as abnormal cases * 3GPP TS 24.301, section 5.5.1.2.6, case d */ - _emm_attach_abnormal_cases_bcd(&emm_sap); + _emm_attach_abnormal_cases_bcd(user, &emm_sap); break; } - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); /* * Notify ESM that the network rejected connectivity to the PDN @@ -690,7 +682,7 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; esm_sap.is_standalone = FALSE; esm_sap.recv = esm_msg_pP; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); } LOG_FUNC_RETURN(rc); @@ -714,13 +706,14 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data, _emm_attach_data ** ** ** ***************************************************************************/ int emm_proc_attach_complete(void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_attach_data_t *emm_attach_data = user->emm_data->emm_attach_data; emm_sap_t emm_sap; esm_sap_t esm_sap; int rc; @@ -728,22 +721,22 @@ int emm_proc_attach_complete(void *args) LOG_TRACE(INFO, "EMM-PROC - EPS attach complete"); /* Reset EMM procedure handler */ - (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); /* Reset the attach attempt counter */ - _emm_attach_data.attempt_count = 0; + emm_attach_data->attempt_count = 0; /* TODO: Reset the tracking area updating attempt counter */ /* Set the EPS update status to EU1 UPDATED */ - _emm_data.status = EU1_UPDATED; - _emm_data.is_attached = TRUE; + user->emm_data->status = EU1_UPDATED; + user->emm_data->is_attached = TRUE; /* * Notify EMM that network attach complete message has been delivered * to the network */ emm_sap.primitive = EMMREG_ATTACH_CNF; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* @@ -753,7 +746,7 @@ int emm_proc_attach_complete(void *args) */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_CNF; esm_sap.is_standalone = FALSE; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); } LOG_FUNC_RETURN(rc); @@ -786,19 +779,20 @@ int emm_proc_attach_complete(void *args) int emm_proc_attach_failure(int is_initial, void *args) { LOG_FUNC_IN; - int rc = RETURNok; esm_sap_t esm_sap; + nas_user_t *user=args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - EPS attach failure"); /* Reset EMM procedure handler */ - (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); /* Stop timer T3410 if still running */ - if (T3410.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); - T3410.id = nas_timer_stop(T3410.id); + if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", emm_timers->T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); } if (is_initial) { @@ -821,13 +815,13 @@ int emm_proc_attach_failure(int is_initial, void *args) esm_sap.recv = NULL; } - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); if (rc != RETURNerror) { /* Start T3411 timer */ - T3411.id = nas_timer_start(T3411.sec, _emm_attach_t3411_handler, NULL); + emm_timers->T3411.id = nas_timer_start(emm_timers->T3411.sec, _emm_attach_t3411_handler, NULL); LOG_TRACE(INFO, "EMM-PROC - Timer T3411 (%d) expires in %ld seconds", - T3411.id, T3411.sec); + emm_timers->T3411.id, emm_timers->T3411.sec); } LOG_FUNC_RETURN(rc); @@ -855,16 +849,16 @@ int emm_proc_attach_failure(int is_initial, void *args) int emm_proc_attach_release(void *args) { LOG_FUNC_IN; - + nas_user_t *user=args; emm_sap_t emm_sap; int rc; LOG_TRACE(WARNING, "EMM-PROC - NAS signalling connection released"); /* Execute abnormal case attach procedure */ - _emm_attach_abnormal_cases_bcd(&emm_sap); + _emm_attach_abnormal_cases_bcd(user, &emm_sap); - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -883,7 +877,7 @@ int emm_proc_attach_release(void *args) ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_attach_restart(void) +int emm_proc_attach_restart(nas_user_t *user) { LOG_FUNC_IN; @@ -896,8 +890,8 @@ int emm_proc_attach_restart(void) * Notify EMM that the attach procedure has to be restarted */ emm_sap.primitive = EMMREG_ATTACH_INIT; - emm_sap.u.emm_reg.u.attach.is_emergency = _emm_data.is_emergency; - rc = emm_sap_send(&emm_sap); + emm_sap.u.emm_reg.u.attach.is_emergency = user->emm_data->is_emergency; + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -913,17 +907,17 @@ int emm_proc_attach_restart(void) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -int emm_proc_attach_set_emergency(void) +int emm_proc_attach_set_emergency(emm_data_t *emm_data) { LOG_FUNC_IN; LOG_TRACE(WARNING, "EMM-PROC - UE is now attached to the network for " "emergency bearer services only"); - _emm_data.is_emergency = TRUE; + emm_data->is_emergency = TRUE; LOG_FUNC_RETURN(RETURNok); } @@ -940,26 +934,27 @@ int emm_proc_attach_set_emergency(void) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -int emm_proc_attach_set_detach(void) +int emm_proc_attach_set_detach(void *nas_user) { LOG_FUNC_IN; + nas_user_t *user=nas_user; int rc; LOG_TRACE(WARNING, "EMM-PROC - UE is now locally detached from the network"); /* Reset the network attachment indicator */ - _emm_data.is_attached = FALSE; + user->emm_data->is_attached = FALSE; /* * Notify that the UE is locally detached from the network */ emm_sap_t emm_sap; emm_sap.primitive = EMMREG_DETACH_CNF; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -995,25 +990,27 @@ int emm_proc_attach_set_detach(void) ** Others: T3410 ** ** ** ***************************************************************************/ -void *_emm_attach_t3410_handler(void *args) +void *emm_attach_t3410_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user=args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; emm_sap_t emm_sap; int rc; LOG_TRACE(WARNING, "EMM-PROC - T3410 timer expired"); /* Stop T3410 timer */ - T3410.id = nas_timer_stop(T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); /* Execute abnormal case attach procedure */ - _emm_attach_abnormal_cases_bcd(&emm_sap); + _emm_attach_abnormal_cases_bcd(user, &emm_sap); - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Locally release the NAS signalling connection */ - _emm_data.ecm_status = ECM_IDLE; + user->emm_data->ecm_status = ECM_IDLE; } LOG_FUNC_RETURN(NULL); @@ -1041,20 +1038,22 @@ static void *_emm_attach_t3411_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user=args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; emm_sap_t emm_sap; LOG_TRACE(WARNING, "EMM-PROC - T3411 timer expired"); /* Stop T3411 timer */ - T3411.id = nas_timer_stop(T3411.id); + emm_timers->T3411.id = nas_timer_stop(emm_timers->T3411.id); /* * Notify EMM that timer T3411 expired and attach procedure has to be * restarted */ emm_sap.primitive = EMMREG_ATTACH_INIT; - emm_sap.u.emm_reg.u.attach.is_emergency = _emm_data.is_emergency; + emm_sap.u.emm_reg.u.attach.is_emergency = user->emm_data->is_emergency; - (void) emm_sap_send(&emm_sap); + (void) emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(NULL); } @@ -1078,29 +1077,31 @@ static void *_emm_attach_t3411_handler(void *args) ** ** ** Outputs: None ** ** Return: None ** - ** Others: _emm_attach_data, T3402 ** ** ** ***************************************************************************/ static void *_emm_attach_t3402_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; + emm_attach_data_t *emm_attach_data = user->emm_data->emm_attach_data; emm_sap_t emm_sap; LOG_TRACE(WARNING, "EMM-PROC - T3402 timer expired"); /* Stop T3402 timer */ - T3402.id = nas_timer_stop(T3402.id); + emm_timers->T3402.id = nas_timer_stop(emm_timers->T3402.id); /* Reset the attach attempt counter */ - _emm_attach_data.attempt_count = 0; + emm_attach_data->attempt_count = 0; /* * Notify EMM that timer T3402 expired and attach procedure has to be * restarted */ emm_sap.primitive = EMMREG_ATTACH_INIT; - emm_sap.u.emm_reg.u.attach.is_emergency = _emm_data.is_emergency; + emm_sap.u.emm_reg.u.attach.is_emergency = user->emm_data->is_emergency; - (void) emm_sap_send(&emm_sap); + (void) emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(NULL); } @@ -1128,30 +1129,30 @@ static void *_emm_attach_t3402_handler(void *args) ** ** ** Outputs: emm_sap: EMM service access point ** ** Return: None ** - ** Others: _emm_data, _emm_attach_data, T3402, T3410, ** ** T3411 ** ** ** ***************************************************************************/ -static void _emm_attach_abnormal_cases_bcd(emm_sap_t *emm_sap) +static void _emm_attach_abnormal_cases_bcd(nas_user_t *user, emm_sap_t *emm_sap) { LOG_FUNC_IN; - + emm_timers_t *emm_timers = user->emm_data->emm_timers; + emm_attach_data_t *emm_attach_data = user->emm_data->emm_attach_data; LOG_TRACE(WARNING, "EMM-PROC - Abnormal case, attach counter = %d", - _emm_attach_data.attempt_count); + emm_attach_data->attempt_count); /* Stop timer T3410 */ - if (T3410.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); - T3410.id = nas_timer_stop(T3410.id); + if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", emm_timers->T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); } - if (_emm_attach_data.attempt_count < EMM_ATTACH_COUNTER_MAX) { + if (emm_attach_data->attempt_count < EMM_ATTACH_COUNTER_MAX) { /* Increment the attach attempt counter */ - _emm_attach_data.attempt_count += 1; + emm_attach_data->attempt_count += 1; /* Start T3411 timer */ - T3411.id = nas_timer_start(T3411.sec, _emm_attach_t3411_handler, NULL); + emm_timers->T3411.id = nas_timer_start(emm_timers->T3411.sec, _emm_attach_t3411_handler, NULL); LOG_TRACE(INFO, "EMM-PROC - Timer T3411 (%d) expires in %ld seconds", - T3411.id, T3411.sec); + emm_timers->T3411.id, emm_timers->T3411.sec); /* * Notify EMM that the attempt to attach for EPS services failed and * the attach attempt counter didn't reach its maximum value; network @@ -1160,26 +1161,26 @@ static void _emm_attach_abnormal_cases_bcd(emm_sap_t *emm_sap) emm_sap->primitive = EMMREG_ATTACH_FAILED; } else { /* Delete the GUTI */ - _emm_data.guti = NULL; + user->emm_data->guti = NULL; /* Delete the TAI list */ - _emm_data.ltai.n_tais = 0; + user->emm_data->ltai.n_tais = 0; /* Delete the last visited registered TAI */ - _emm_data.tai = NULL; + user->emm_data->tai = NULL; /* Delete the list of equivalent PLMNs */ - _emm_data.nvdata.eplmn.n_plmns = 0; + user->emm_data->nvdata.eplmn.n_plmns = 0; /* Delete the eKSI */ - if (_emm_data.security) { - _emm_data.security->type = EMM_KSI_NOT_AVAILABLE; + if (user->emm_data->security) { + user->emm_data->security->type = EMM_KSI_NOT_AVAILABLE; } /* Set the EPS update status to EU2 NOT UPDATED */ - _emm_data.status = EU2_NOT_UPDATED; + user->emm_data->status = EU2_NOT_UPDATED; /* Start T3402 timer */ - T3402.id = nas_timer_start(T3402.sec, _emm_attach_t3402_handler, NULL); + emm_timers->T3402.id = nas_timer_start(emm_timers->T3402.sec, _emm_attach_t3402_handler, user); LOG_TRACE(INFO, "EMM-PROC - Timer T3402 (%d) expires in %ld seconds", - T3402.id, T3402.sec); + emm_timers->T3402.id, emm_timers->T3402.sec); /* * Notify EMM that the attempt to attach for EPS services failed and * the attach attempt counter reached its maximum value. diff --git a/openair3/NAS/UE/EMM/Authentication.c b/openair3/NAS/UE/EMM/Authentication.c index 9022acbdac8d1a3cc4e6f9602dacb2572b79a323..e49bdd2db7e5e36aa52835dd58b8f477bd3317a9 100644 --- a/openair3/NAS/UE/EMM/Authentication.c +++ b/openair3/NAS/UE/EMM/Authentication.c @@ -59,26 +59,21 @@ Description Defines the authentication EMM procedure executed by the #include "nas_timer.h" #include "emmData.h" +#include "emm_timers.h" #include "emm_sap.h" #include "emm_cause.h" +#include "emm_timers.h" #include "usim_api.h" #include "secu_defs.h" +#include "Authentication.h" /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ -/* - * Retransmission timer handlers - */ -extern void *_emm_attach_t3410_handler(void *); -extern void *_emm_service_t3417_handler(void *); -extern void *_emm_detach_t3421_handler(void *); -extern void *_emm_tau_t3430_handler(void *); - extern uint8_t usim_test; /****************************************************************************/ @@ -97,34 +92,15 @@ static void *_authentication_t3416_handler(void *); static void *_authentication_t3418_handler(void *); static void *_authentication_t3420_handler(void *); -/* - * Internal data used for authentication procedure - */ -static struct { - uint8_t rand[AUTH_RAND_SIZE]; /* Random challenge number */ - uint8_t res[AUTH_RES_SIZE]; /* Authentication response */ - uint8_t ck[AUTH_CK_SIZE]; /* Ciphering key */ - uint8_t ik[AUTH_IK_SIZE]; /* Integrity key */ -#define AUTHENTICATION_T3410 0x01 -#define AUTHENTICATION_T3417 0x02 -#define AUTHENTICATION_T3421 0x04 -#define AUTHENTICATION_T3430 0x08 - unsigned char timers; /* Timer restart bitmap */ -#define AUTHENTICATION_COUNTER_MAX 3 - unsigned char mac_count:2; /* MAC failure counter (#20) */ - unsigned char umts_count:2; /* UMTS challenge failure counter (#26) */ - unsigned char sync_count:2; /* Sync failure counter (#21) */ -} _authentication_data; - /* * Abnormal case authentication procedure */ -static int _authentication_abnormal_cases_cde(int emm_cause, +static int _authentication_abnormal_cases_cde(nas_user_t *user, int emm_cause, const OctetString *auts); -static int _authentication_abnormal_case_f(void); +static int _authentication_abnormal_case_f(nas_user_t *user); -static int _authentication_stop_timers(void); -static int _authentication_start_timers(void); +static int _authentication_stop_timers(nas_user_t *user); +static int _authentication_start_timers(nas_user_t *user); static int _authentication_kasme(const OctetString *autn, const OctetString *ck, const OctetString *ik, const plmn_t *plmn, OctetString *kasme); @@ -163,21 +139,21 @@ static int _authentication_kasme(const OctetString *autn, ** ksi: The NAS ket sey identifier ** ** rand: Authentication parameter RAND ** ** autn: Authentication parameter AUTN ** - ** Others: _emm_data, _authentication_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data, _authentication_data, T3416, ** ** T3418, T3420 ** ** ** ***************************************************************************/ -int emm_proc_authentication_request(int native_ksi, int ksi, +int emm_proc_authentication_request(nas_user_t *user, int native_ksi, int ksi, const OctetString *rand, const OctetString *autn) { LOG_FUNC_IN; int rc = RETURNerror; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(INFO, "EMM-PROC - Authentication requested ksi type = %s, ksi = %d", native_ksi ? "native" : "mapped", ksi); @@ -185,29 +161,29 @@ int emm_proc_authentication_request(int native_ksi, int ksi, * The UE shall proceed with an EPS authentication challenge only if a * USIM is present */ - if (!_emm_data.usim_is_valid) { + if (!user->emm_data->usim_is_valid) { LOG_TRACE(WARNING, "EMM-PROC - USIM is not present or not valid"); LOG_FUNC_RETURN (RETURNerror); } /* Stop timer T3418, if running */ - if (T3418.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3418 (%d)", T3418.id); - T3418.id = nas_timer_stop(T3418.id); + if (emm_timers->T3418.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3418 (%d)", emm_timers->T3418.id); + emm_timers->T3418.id = nas_timer_stop(emm_timers->T3418.id); } /* Stop timer T3420, if running */ - if (T3420.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3420 (%d)", T3420.id); - T3420.id = nas_timer_stop(T3420.id); + if (emm_timers->T3420.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3420 (%d)", emm_timers->T3420.id); + emm_timers->T3420.id = nas_timer_stop(emm_timers->T3420.id); } /* Setup security keys */ - OctetString ck = {AUTH_CK_SIZE, _authentication_data.ck}; - OctetString ik = {AUTH_IK_SIZE, _authentication_data.ik}; - OctetString res = {AUTH_RES_SIZE, _authentication_data.res}; + OctetString ck = {AUTH_CK_SIZE, authentication_data->ck}; + OctetString ik = {AUTH_IK_SIZE, authentication_data->ik}; + OctetString res = {AUTH_RES_SIZE, authentication_data->res}; - if (memcmp(_authentication_data.rand, rand->value, AUTH_CK_SIZE) != 0) { + if (memcmp(authentication_data->rand, rand->value, AUTH_CK_SIZE) != 0) { /* * There is no valid stored RAND in the ME or the stored RAND is * different from the new received value in the AUTHENTICATION @@ -237,11 +213,11 @@ int emm_proc_authentication_request(int native_ksi, int ksi, */ if(usim_test == 0) { - rc = usim_api_authenticate(rand, autn, &auts, &res, &ck, &ik); + rc = usim_api_authenticate(&user->usim_data, rand, autn, &auts, &res, &ck, &ik); } else { - rc = usim_api_authenticate_test(rand, autn, &auts, &res, &ck, &ik); // XOR algo for autentication on usim test mode + rc = usim_api_authenticate_test(&user->usim_data, rand, autn, &auts, &res, &ck, &ik); } } @@ -254,24 +230,24 @@ int emm_proc_authentication_request(int native_ksi, int ksi, (sbit == 0) ? "Non-EPS authentication unacceptable" : "MAC code failure"); /* Delete any previously stored RAND and RES and stop timer T3416 */ - (void) emm_proc_authentication_delete(); + emm_proc_authentication_delete(user); /* Proceed authentication abnormal cases procedure */ if (auts.length > 0) { /* 3GPP TS 24.301, section 5.4.2.6, case e * SQN failure */ rc = _authentication_abnormal_cases_cde( - EMM_CAUSE_SYNCH_FAILURE, &auts); + user, EMM_CAUSE_SYNCH_FAILURE, &auts); } else if (sbit == 0) { /* 3GPP TS 24.301, section 5.4.2.6, case d * Non-EPS authentication unacceptable */ rc = _authentication_abnormal_cases_cde( - EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE, NULL); + user, EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE, NULL); } else { /* 3GPP TS 24.301, section 5.4.2.6, case c * MAC code failure */ rc = _authentication_abnormal_cases_cde( - EMM_CAUSE_MAC_FAILURE, NULL); + user, EMM_CAUSE_MAC_FAILURE, NULL); } /* Free the AUTS parameter */ @@ -284,18 +260,18 @@ int emm_proc_authentication_request(int native_ksi, int ksi, /* Store the new RAND in the volatile memory */ if (rand->length <= AUTH_RAND_SIZE) { - memcpy(_authentication_data.rand, rand->value, rand->length); + memcpy(authentication_data->rand, rand->value, rand->length); } /* Start, or reset and restart timer T3416 */ - if (T3416.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", T3416.id); - T3416.id = nas_timer_stop(T3416.id); + if (emm_timers->T3416.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", emm_timers->T3416.id); + emm_timers->T3416.id = nas_timer_stop(emm_timers->T3416.id); } - T3416.id = nas_timer_start(T3416.sec, _authentication_t3416_handler, NULL); + emm_timers->T3416.id = nas_timer_start(emm_timers->T3416.sec, _authentication_t3416_handler, NULL); LOG_TRACE(INFO, "EMM-PROC - Timer T3416 (%d) expires in %ld seconds", - T3416.id, T3416.sec); + emm_timers->T3416.id, emm_timers->T3416.sec); } /* @@ -304,7 +280,7 @@ int emm_proc_authentication_request(int native_ksi, int ksi, * the authenticity of the core network */ /* Start any retransmission timers */ - rc = _authentication_start_timers(); + rc = _authentication_start_timers(user); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - Failed to start retransmission timers"); @@ -313,7 +289,7 @@ int emm_proc_authentication_request(int native_ksi, int ksi, /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ - rc = emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); if (rc != RETURNok) { LOG_TRACE(WARNING, @@ -327,46 +303,46 @@ int emm_proc_authentication_request(int native_ksi, int ksi, */ emm_sap_t emm_sap; emm_sap.primitive = EMMAS_SECURITY_RES; - emm_sap.u.emm_as.u.security.guti = _emm_data.guti; - emm_sap.u.emm_as.u.security.ueid = 0; + emm_sap.u.emm_as.u.security.guti = user->emm_data->guti; + emm_sap.u.emm_as.u.security.ueid = user->ueid; emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_AUTH; emm_sap.u.emm_as.u.security.emm_cause = EMM_CAUSE_SUCCESS; emm_sap.u.emm_as.u.security.res = &res; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - _emm_data.security, FALSE, TRUE); - rc = emm_sap_send(&emm_sap); + user->emm_data->security, FALSE, TRUE); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Reset the authentication failure counters */ - _authentication_data.mac_count = 0; - _authentication_data.umts_count = 0; - _authentication_data.sync_count = 0; + authentication_data->mac_count = 0; + authentication_data->umts_count = 0; + authentication_data->sync_count = 0; /* Create non-current EPS security context */ - if (_emm_data.non_current == NULL) { - _emm_data.non_current = + if (user->emm_data->non_current == NULL) { + user->emm_data->non_current = (emm_security_context_t *)malloc(sizeof(emm_security_context_t)); } - if (_emm_data.non_current) { - memset(_emm_data.non_current, 0, sizeof(emm_security_context_t)); + if (user->emm_data->non_current) { + memset(user->emm_data->non_current, 0, sizeof(emm_security_context_t)); /* Set the security context type */ if (native_ksi) { - _emm_data.non_current->type = EMM_KSI_NATIVE; + user->emm_data->non_current->type = EMM_KSI_NATIVE; } else { - _emm_data.non_current->type = EMM_KSI_MAPPED; + user->emm_data->non_current->type = EMM_KSI_MAPPED; } /* Set the EPS key set identifier */ - _emm_data.non_current->eksi = ksi; + user->emm_data->non_current->eksi = ksi; /* Derive the Kasme from the authentication challenge using * the PLMN identity of the selected PLMN */ - _emm_data.non_current->kasme.length = AUTH_KASME_SIZE; - _emm_data.non_current->kasme.value = malloc(32); - _authentication_kasme(autn, &ck, &ik, &_emm_data.splmn, - &_emm_data.non_current->kasme); + user->emm_data->non_current->kasme.length = AUTH_KASME_SIZE; + user->emm_data->non_current->kasme.value = malloc(32); + _authentication_kasme(autn, &ck, &ik, &user->emm_data->splmn, + &user->emm_data->non_current->kasme); /* NAS integrity and cyphering keys are not yet available */ } } @@ -392,66 +368,67 @@ int emm_proc_authentication_request(int native_ksi, int ksi, ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data, _authentication_data, T3410, ** ** T3417, T3430 ** ** ** ***************************************************************************/ -int emm_proc_authentication_reject(void) +int emm_proc_authentication_reject(nas_user_t *user) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - Authentication not accepted by the network"); /* Delete any previously stored RAND and RES and stop timer T3416 */ - (void) emm_proc_authentication_delete(); + (void) emm_proc_authentication_delete(user); /* Set the EPS update status to EU3 ROAMING NOT ALLOWED */ - _emm_data.status = EU3_ROAMING_NOT_ALLOWED; + user->emm_data->status = EU3_ROAMING_NOT_ALLOWED; /* Delete the stored GUTI */ - _emm_data.guti = NULL; + user->emm_data->guti = NULL; /* Delete the TAI list */ - _emm_data.ltai.n_tais = 0; + user->emm_data->ltai.n_tais = 0; /* Delete the last visited registered TAI */ - _emm_data.tai = NULL; + user->emm_data->tai = NULL; /* Delete the eKSI */ - if (_emm_data.security) { - _emm_data.security->type = EMM_KSI_NOT_AVAILABLE; + if (user->emm_data->security) { + user->emm_data->security->type = EMM_KSI_NOT_AVAILABLE; } /* Consider the USIM invalid */ - _emm_data.usim_is_valid = FALSE; + user->emm_data->usim_is_valid = FALSE; /* Stop timer T3410 */ - if (T3410.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); - T3410.id = nas_timer_stop(T3410.id); + if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", emm_timers->T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); } /* Stop timer T3417 */ - if (T3417.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", T3417.id); - T3417.id = nas_timer_stop(T3417.id); + if (emm_timers->T3417.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", emm_timers->T3417.id); + emm_timers->T3417.id = nas_timer_stop(emm_timers->T3417.id); } /* Stop timer T3430 */ - if (T3430.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", T3430.id); - T3430.id = nas_timer_stop(T3430.id); + if (emm_timers->T3430.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", emm_timers->T3430.id); + emm_timers->T3430.id = nas_timer_stop(emm_timers->T3430.id); } /* Abort any EMM signalling procedure (prevent the retransmission timers to * be restarted) */ - _authentication_data.timers = 0x00; + authentication_data->timers = 0x00; /* * Notify EMM that authentication is not accepted by the network */ emm_sap.primitive = EMMREG_AUTH_REJ; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -475,24 +452,25 @@ int emm_proc_authentication_reject(void) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _authentication_data, T3416 ** ** ** ***************************************************************************/ -int emm_proc_authentication_delete(void) +int emm_proc_authentication_delete(nas_user_t *user) { LOG_FUNC_IN; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(INFO, "EMM-PROC - Delete authentication data RAND and RES"); /* Stop timer T3416, if running */ - if (T3416.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", T3416.id); - T3416.id = nas_timer_stop(T3416.id); + if (emm_timers->T3416.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", emm_timers->T3416.id); + emm_timers->T3416.id = nas_timer_stop(emm_timers->T3416.id); } /* Delete any previously stored RAND and RES */ - memset(_authentication_data.rand, 0, AUTH_RAND_SIZE); - memset(_authentication_data.res, 0, AUTH_RES_SIZE); + memset(authentication_data->rand, 0, AUTH_RAND_SIZE); + memset(authentication_data->res, 0, AUTH_RES_SIZE); LOG_FUNC_RETURN (RETURNok); } @@ -529,13 +507,15 @@ int emm_proc_authentication_delete(void) static void *_authentication_t3416_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user=args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - T3416 timer expired"); /* Stop timer T3416 */ - T3416.id = nas_timer_stop(T3416.id); + emm_timers->T3416.id = nas_timer_stop(emm_timers->T3416.id); /* Delete previouly stored RAND and RES authentication data */ - (void) emm_proc_authentication_delete(); + (void) emm_proc_authentication_delete(user); LOG_FUNC_RETURN (NULL); } @@ -556,7 +536,6 @@ static void *_authentication_t3416_handler(void *args) ** ** ** Outputs: None ** ** Return: None ** - ** Others: _authentication_data, T3418 ** ** ** ***************************************************************************/ static void *_authentication_t3418_handler(void *args) @@ -564,16 +543,19 @@ static void *_authentication_t3418_handler(void *args) LOG_FUNC_IN; int rc; + nas_user_t *user=args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; + authentication_data_t *authentication_data = user->authentication_data; LOG_TRACE(WARNING, "EMM-PROC - T3418 timer expired"); /* Stop timer T3418 */ - T3418.id = nas_timer_stop(T3418.id); + emm_timers->T3418.id = nas_timer_stop(emm_timers->T3418.id); /* Reset the MAC failure and UMTS challenge failure counters */ - _authentication_data.mac_count = 0; - _authentication_data.umts_count = 0; + authentication_data->mac_count = 0; + authentication_data->umts_count = 0; /* 3GPP TS 24.301, section 5.4.2.7, case f */ - rc = _authentication_abnormal_case_f(); + rc = _authentication_abnormal_case_f(user); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - Failed to proceed abnormal case f"); @@ -597,7 +579,6 @@ static void *_authentication_t3418_handler(void *args) ** ** ** Outputs: None ** ** Return: None ** - ** Others: _authentication_data, T3420 ** ** ** ***************************************************************************/ static void *_authentication_t3420_handler(void *args) @@ -605,15 +586,18 @@ static void *_authentication_t3420_handler(void *args) LOG_FUNC_IN; int rc; + nas_user_t *user=args; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - T3420 timer expired"); /* Stop timer T3420 */ - T3420.id = nas_timer_stop(T3420.id); + emm_timers->T3420.id = nas_timer_stop(emm_timers->T3420.id); /* Reset the sync failure counter */ - _authentication_data.sync_count = 0; + authentication_data->sync_count = 0; /* 3GPP TS 24.301, section 5.4.2.7, case f */ - rc = _authentication_abnormal_case_f(); + rc = _authentication_abnormal_case_f(user); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - Failed to proceed abnormal case f"); @@ -641,20 +625,21 @@ static void *_authentication_t3420_handler(void *args) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _authentication_data, T3418, T3420 ** ** ** ***************************************************************************/ -static int _authentication_abnormal_cases_cde(int emm_cause, +static int _authentication_abnormal_cases_cde(nas_user_t *user, int emm_cause, const OctetString *auts) { LOG_FUNC_IN; int rc; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - " "Abnormal case, authentication counters c/d/e = %d/%d/%d", - _authentication_data.mac_count, _authentication_data.umts_count, - _authentication_data.sync_count); + authentication_data->mac_count, authentication_data->umts_count, + authentication_data->sync_count); /* * Notify EMM-AS SAP that Authentication Failure message has to be sent @@ -662,15 +647,15 @@ static int _authentication_abnormal_cases_cde(int emm_cause, */ emm_sap_t emm_sap; emm_sap.primitive = EMMAS_SECURITY_RES; - emm_sap.u.emm_as.u.security.guti = _emm_data.guti; - emm_sap.u.emm_as.u.security.ueid = 0; + emm_sap.u.emm_as.u.security.guti = user->emm_data->guti; + emm_sap.u.emm_as.u.security.ueid = user->ueid; emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_AUTH; emm_sap.u.emm_as.u.security.emm_cause = emm_cause; emm_sap.u.emm_as.u.security.auts = auts; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - _emm_data.security, FALSE, TRUE); - rc = emm_sap_send(&emm_sap); + user->emm_data->security, FALSE, TRUE); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* @@ -680,34 +665,34 @@ static int _authentication_abnormal_cases_cde(int emm_cause, case EMM_CAUSE_MAC_FAILURE: /* 3GPP TS 24.301, section 5.4.2.6, case c * Update the MAC failure counter */ - _authentication_data.mac_count += 1; + authentication_data->mac_count += 1; /* Start timer T3418 */ - T3418.id = nas_timer_start(T3418.sec, - _authentication_t3418_handler, NULL); + emm_timers->T3418.id = nas_timer_start(emm_timers->T3418.sec, + _authentication_t3418_handler, user); LOG_TRACE(INFO,"EMM-PROC - Timer T3418 (%d) expires in " - "%ld seconds", T3418.id, T3418.sec); + "%ld seconds", emm_timers->T3418.id, emm_timers->T3418.sec); break; case EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE: /* 3GPP TS 24.301, section 5.4.2.6, case d * Update the UMTS challenge failure counter */ - _authentication_data.umts_count += 1; + authentication_data->umts_count += 1; /* Start timer T3418 */ - T3418.id = nas_timer_start(T3418.sec, - _authentication_t3418_handler, NULL); + emm_timers->T3418.id = nas_timer_start(emm_timers->T3418.sec, + _authentication_t3418_handler, user); LOG_TRACE(INFO,"EMM-PROC - Timer T3418 (%d) expires in " - "%ld seconds", T3418.id, T3418.sec); + "%ld seconds", emm_timers->T3418.id, emm_timers->T3418.sec); break; case EMM_CAUSE_SYNCH_FAILURE: /* 3GPP TS 24.301, section 5.4.2.6, case e * Update the synch failure counter */ - _authentication_data.sync_count += 1; + authentication_data->sync_count += 1; /* Start timer T3420 */ - T3420.id = nas_timer_start(T3420.sec, - _authentication_t3420_handler, NULL); + emm_timers->T3420.id = nas_timer_start(emm_timers->T3420.sec, + _authentication_t3420_handler, user); LOG_TRACE(INFO,"EMM-PROC - Timer T3420 (%d) expires in " - "%ld seconds", T3420.id, T3420.sec); + "%ld seconds", emm_timers->T3420.id, emm_timers->T3420.sec); break; default: @@ -719,7 +704,7 @@ static int _authentication_abnormal_cases_cde(int emm_cause, /* * Stop any retransmission timers that are running */ - rc = _authentication_stop_timers(); + rc = _authentication_stop_timers(user); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - " @@ -733,17 +718,17 @@ static int _authentication_abnormal_cases_cde(int emm_cause, int failure_counter = 0; if (emm_cause == EMM_CAUSE_MAC_FAILURE) { - failure_counter = _authentication_data.mac_count - + _authentication_data.sync_count; + failure_counter = authentication_data->mac_count + + authentication_data->sync_count; } else if (emm_cause == EMM_CAUSE_SYNCH_FAILURE) { - failure_counter = _authentication_data.mac_count - + _authentication_data.umts_count - + _authentication_data.sync_count; + failure_counter = authentication_data->mac_count + + authentication_data->umts_count + + authentication_data->sync_count; } if (failure_counter >= AUTHENTICATION_COUNTER_MAX) { /* 3GPP TS 24.301, section 5.4.2.6, case f */ - rc = _authentication_abnormal_case_f(); + rc = _authentication_abnormal_case_f(user); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - " @@ -771,7 +756,7 @@ static int _authentication_abnormal_cases_cde(int emm_cause, ** Others: None ** ** ** ***************************************************************************/ -static int _authentication_abnormal_case_f(void) +static int _authentication_abnormal_case_f(nas_user_t *user) { LOG_FUNC_IN; @@ -785,16 +770,16 @@ static int _authentication_abnormal_case_f(void) */ emm_sap_t emm_sap; emm_sap.primitive = EMMAS_RELEASE_REQ; - emm_sap.u.emm_as.u.release.guti = _emm_data.guti; + emm_sap.u.emm_as.u.release.guti = user->emm_data->guti; emm_sap.u.emm_as.u.release.cause = EMM_AS_CAUSE_AUTHENTICATION; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Start any retransmission timers (e.g. T3410, T3417, T3421 or * T3430), if they were running and stopped when the UE received * the first AUTHENTICATION REQUEST message containing an invalid * MAC or SQN */ - rc = _authentication_start_timers(); + rc = _authentication_start_timers(user); } LOG_FUNC_RETURN (rc); @@ -818,40 +803,41 @@ static int _authentication_abnormal_case_f(void) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _authentication_data, T3410, T3417, T3421, ** ** T3430 ** ** ** ***************************************************************************/ -static int _authentication_stop_timers(void) +static int _authentication_stop_timers(nas_user_t *user) { LOG_FUNC_IN; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; /* Stop attach timer */ - if (T3410.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id); - T3410.id = nas_timer_stop(T3410.id); - _authentication_data.timers |= AUTHENTICATION_T3410; + if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", emm_timers->T3410.id); + emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id); + authentication_data->timers |= AUTHENTICATION_T3410; } /* Stop service request timer */ - if (T3417.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", T3417.id); - T3417.id = nas_timer_stop(T3417.id); - _authentication_data.timers |= AUTHENTICATION_T3417; + if (emm_timers->T3417.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", emm_timers->T3417.id); + emm_timers->T3417.id = nas_timer_stop(emm_timers->T3417.id); + authentication_data->timers |= AUTHENTICATION_T3417; } /* Stop detach timer */ - if (T3421.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3421 (%d)", T3421.id); - T3421.id = nas_timer_stop(T3421.id); - _authentication_data.timers |= AUTHENTICATION_T3421; + if (emm_timers->T3421.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3421 (%d)", emm_timers->T3421.id); + emm_timers->T3421.id = nas_timer_stop(emm_timers->T3421.id); + authentication_data->timers |= AUTHENTICATION_T3421; } /* Stop tracking area update timer */ - if (T3430.id != NAS_TIMER_INACTIVE_ID) { - LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", T3430.id); - T3430.id = nas_timer_stop(T3430.id); - _authentication_data.timers |= AUTHENTICATION_T3430; + if (emm_timers->T3430.id != NAS_TIMER_INACTIVE_ID) { + LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", emm_timers->T3430.id); + emm_timers->T3430.id = nas_timer_stop(emm_timers->T3430.id); + authentication_data->timers |= AUTHENTICATION_T3430; } LOG_FUNC_RETURN (RETURNok); @@ -869,43 +855,44 @@ static int _authentication_stop_timers(void) ** 3GPP TS 24.301, section 5.4.2.7, case f ** ** ** ** Inputs: None ** - ** Others: _authentication_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: T3410, T3417, T3421, T3430 ** ** ** ***************************************************************************/ -static int _authentication_start_timers(void) +static int _authentication_start_timers(nas_user_t *user) { LOG_FUNC_IN; + authentication_data_t *authentication_data = user->authentication_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; - if (_authentication_data.timers & AUTHENTICATION_T3410) { + if (authentication_data->timers & AUTHENTICATION_T3410) { /* Start attach timer */ - T3410.id = nas_timer_start(T3410.sec, _emm_attach_t3410_handler, NULL); + emm_timers->T3410.id = nas_timer_start(emm_timers->T3410.sec, emm_attach_t3410_handler, NULL); LOG_TRACE(INFO,"EMM-PROC - Timer T3410 (%d) expires in " - "%ld seconds", T3410.id, T3410.sec); + "%ld seconds", emm_timers->T3410.id, emm_timers->T3410.sec); } - if (_authentication_data.timers & AUTHENTICATION_T3417) { + if (authentication_data->timers & AUTHENTICATION_T3417) { /* Start service request timer */ - T3417.id = nas_timer_start(T3417.sec, _emm_service_t3417_handler, NULL); + emm_timers->T3417.id = nas_timer_start(emm_timers->T3417.sec, emm_service_t3417_handler, NULL); LOG_TRACE(INFO,"EMM-PROC - Timer T3417 (%d) expires in " - "%ld seconds", T3417.id, T3417.sec); + "%ld seconds", emm_timers->T3417.id, emm_timers->T3417.sec); } - if (_authentication_data.timers & AUTHENTICATION_T3421) { + if (authentication_data->timers & AUTHENTICATION_T3421) { /* Start detach timer */ - T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL); + emm_timers->T3421.id = nas_timer_start(emm_timers->T3421.sec, emm_detach_t3421_handler, NULL); LOG_TRACE(INFO,"EMM-PROC - Timer T3421 (%d) expires in " - "%ld seconds", T3421.id, T3421.sec); + "%ld seconds", emm_timers->T3421.id, emm_timers->T3421.sec); } - if (_authentication_data.timers & AUTHENTICATION_T3430) { + if (authentication_data->timers & AUTHENTICATION_T3430) { /* Start tracking area update timer */ - T3430.id = nas_timer_start(T3430.sec, _emm_tau_t3430_handler, NULL); + emm_timers->T3430.id = nas_timer_start(emm_timers->T3430.sec, emm_tau_t3430_handler, NULL); LOG_TRACE(INFO,"EMM-PROC - Timer T3430 (%d) expires in " - "%ld seconds", T3430.id, T3430.sec); + "%ld seconds", emm_timers->T3430.id, emm_timers->T3430.sec); } LOG_FUNC_RETURN (RETURNok); diff --git a/openair3/NAS/UE/EMM/Authentication.h b/openair3/NAS/UE/EMM/Authentication.h new file mode 100644 index 0000000000000000000000000000000000000000..50b2d990aa5ba8628a19550bc393b8b0a88604c2 --- /dev/null +++ b/openair3/NAS/UE/EMM/Authentication.h @@ -0,0 +1,23 @@ +#ifndef _AUTHENTICATION_H +#define _AUTHENTICATION_H + +/* + * Internal data used for authentication procedure + */ +typedef struct { + uint8_t rand[AUTH_RAND_SIZE]; /* Random challenge number */ + uint8_t res[AUTH_RES_SIZE]; /* Authentication response */ + uint8_t ck[AUTH_CK_SIZE]; /* Ciphering key */ + uint8_t ik[AUTH_IK_SIZE]; /* Integrity key */ +#define AUTHENTICATION_T3410 0x01 +#define AUTHENTICATION_T3417 0x02 +#define AUTHENTICATION_T3421 0x04 +#define AUTHENTICATION_T3430 0x08 + unsigned char timers; /* Timer restart bitmap */ +#define AUTHENTICATION_COUNTER_MAX 3 + unsigned char mac_count:2; /* MAC failure counter (#20) */ + unsigned char umts_count:2; /* UMTS challenge failure counter (#26) */ + unsigned char sync_count:2; /* Sync failure counter (#21) */ +} authentication_data_t; + +#endif diff --git a/openair3/NAS/UE/EMM/Detach.c b/openair3/NAS/UE/EMM/Detach.c index 7fd73305246ffddd6568cc148037ada478a40f91..fd2db1b6174ae7a9624f875531eaf8b68a2d07b4 100644 --- a/openair3/NAS/UE/EMM/Detach.c +++ b/openair3/NAS/UE/EMM/Detach.c @@ -49,6 +49,7 @@ Description Defines the detach related EMM procedure executed by the #include "nas_timer.h" #include "emmData.h" +#include "emm_timers.h" #include "emm_sap.h" #include "esm_sap.h" @@ -75,29 +76,11 @@ static const char *_emm_detach_type_str[] = { * Internal data handled by the detach procedure in the UE * -------------------------------------------------------------------------- */ -/* - * Timer handlers - */ -void *_emm_detach_t3421_handler(void *); /* * Abnormal case detach procedures */ -static int _emm_detach_abort(emm_proc_detach_type_t type); - -/* - * Internal data used for detach procedure - */ -static struct { -#define EMM_DETACH_COUNTER_MAX 5 - unsigned int count; /* Counter used to limit the number of - * subsequently detach attempts */ - int switch_off; /* UE switch-off indicator */ - emm_proc_detach_type_t type; /* Type of the detach procedure - * currently in progress */ -} _emm_detach_data = {0, FALSE, EMM_DETACH_TYPE_RESERVED}; - - +static int _emm_detach_abort(nas_user_t *user, emm_proc_detach_type_t type); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -124,34 +107,34 @@ static struct { ** Inputs: type: Type of the requested detach ** ** switch_off: Indicates whether the detach is required ** ** because the UE is switched off or not ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_detach_data ** ** ** ***************************************************************************/ -int emm_proc_detach(emm_proc_detach_type_t type, int switch_off) +int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, int switch_off) { LOG_FUNC_IN; emm_sap_t emm_sap; emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data; + emm_detach_data_t *emm_detach_data = user->emm_data->emm_detach_data; int rc; LOG_TRACE(INFO, "EMM-PROC - Initiate EPS detach type = %s (%d)", _emm_detach_type_str[type], type); /* Initialize the detach procedure internal data */ - _emm_detach_data.count = 0; - _emm_detach_data.switch_off = switch_off; - _emm_detach_data.type = type; + emm_detach_data->count = 0; + emm_detach_data->switch_off = switch_off; + emm_detach_data->type = type; /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ - rc = emm_proc_lowerlayer_initialize(emm_proc_detach_request, + rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, emm_proc_detach_request, emm_proc_detach_failure, - emm_proc_detach_release, NULL); + emm_proc_detach_release, user); if (rc != RETURNok) { LOG_TRACE(WARNING, "Failed to initialize EMM procedure handler"); @@ -167,17 +150,17 @@ int emm_proc_detach(emm_proc_detach_type_t type, int switch_off) /* Set the switch-off indicator */ emm_as->switch_off = switch_off; /* Set the EPS mobile identity */ - emm_as->guti = _emm_data.guti; - emm_as->ueid = 0; + emm_as->guti = user->emm_data->guti; + emm_as->ueid = user->ueid; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_as->sctx, _emm_data.security, FALSE, TRUE); + emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, FALSE, TRUE); /* * Notify EMM-AS SAP that Detach Request message has to * be sent to the network */ emm_sap.primitive = EMMAS_DATA_REQ; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -202,21 +185,24 @@ int emm_proc_detach_request(void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; + emm_detach_data_t *emm_detach_data = user->emm_data->emm_detach_data; emm_sap_t emm_sap; int rc; - if ( !_emm_detach_data.switch_off ) { + if ( !emm_detach_data->switch_off ) { /* Start T3421 timer */ - T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL); + emm_timers->T3421.id = nas_timer_start(emm_timers->T3421.sec, emm_detach_t3421_handler, user); LOG_TRACE(INFO, "EMM-PROC - Timer T3421 (%d) expires in %ld seconds", - T3421.id, T3421.sec); + emm_timers->T3421.id, emm_timers->T3421.sec); } /* * Notify EMM that Detach Request has been sent to the network */ emm_sap.primitive = EMMREG_DETACH_REQ; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -243,19 +229,21 @@ int emm_proc_detach_request(void *args) ** Others: T3421 ** ** ** ***************************************************************************/ -int emm_proc_detach_accept(void) +int emm_proc_detach_accept(void* args) { LOG_FUNC_IN; + nas_user_t *user=args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; int rc; LOG_TRACE(INFO, "EMM-PROC - UE initiated detach procedure completion"); /* Reset EMM procedure handler */ - (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + (void) emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); /* Stop timer T3421 */ - T3421.id = nas_timer_stop(T3421.id); + emm_timers->T3421.id = nas_timer_stop(emm_timers->T3421.id); /* * Notify ESM that all EPS bearer contexts have to be locally deactivated @@ -263,7 +251,7 @@ int emm_proc_detach_accept(void) esm_sap_t esm_sap; esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ; esm_sap.data.eps_bearer_context_deactivate.ebi = ESM_SAP_ALL_EBI; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); /* * XXX - Upon receiving notification from ESM that all EPS bearer @@ -285,7 +273,6 @@ int emm_proc_detach_accept(void) ** ** ** Inputs: is_initial: Not used ** ** args: Not used ** - ** Others: _emm_detach_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** @@ -296,23 +283,26 @@ int emm_proc_detach_failure(int is_initial, void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_detach_data_t *emm_detach_data = user->emm_data->emm_detach_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; emm_sap_t emm_sap; int rc; LOG_TRACE(WARNING, "EMM-PROC - Network detach failure"); /* Reset EMM procedure handler */ - (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + (void) emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); /* Stop timer T3421 */ - T3421.id = nas_timer_stop(T3421.id); + emm_timers->T3421.id = nas_timer_stop(emm_timers->T3421.id); /* * Notify EMM that detach procedure has to be restarted */ emm_sap.primitive = EMMREG_DETACH_INIT; - emm_sap.u.emm_reg.u.detach.switch_off = _emm_detach_data.switch_off; - rc = emm_sap_send(&emm_sap); + emm_sap.u.emm_reg.u.detach.switch_off = emm_detach_data->switch_off; + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); } @@ -329,7 +319,6 @@ int emm_proc_detach_failure(int is_initial, void *args) ** The detach procedure shall be aborted. ** ** ** ** Inputs: args: not used ** - ** Others: _emm_detach_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** @@ -342,8 +331,10 @@ int emm_proc_detach_release(void *args) LOG_TRACE(WARNING, "EMM-PROC - NAS signalling connection released"); + nas_user_t *user = args; + emm_detach_data_t *emm_detach_data = user->emm_data->emm_detach_data; /* Abort the detach procedure */ - int rc = _emm_detach_abort(_emm_detach_data.type); + int rc = _emm_detach_abort(user, emm_detach_data->type); LOG_FUNC_RETURN(rc); } @@ -368,50 +359,52 @@ int emm_proc_detach_release(void *args) ** 3GPP TS 24.301, section 5.5.2.2.4 case c ** ** On the first four expiries of the timer, the UE shall re- ** ** transmit the DETACH REQUEST message and shall reset and ** - ** restart timer T3421. On the fifth expiry of timer T3421, ** + ** restart timer emm_timers->T3421. On the fifth expiry of timer T3421, ** ** the detach procedure shall be aborted. ** ** ** ** Inputs: args: handler parameters ** - ** Others: _emm_detach_data ** ** ** ** Outputs: None ** ** Return: None ** ** Others: None ** ** ** ***************************************************************************/ -void *_emm_detach_t3421_handler(void *args) +void *emm_detach_t3421_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_detach_data_t *emm_detach_data = user->emm_data->emm_detach_data; + emm_timers_t *emm_timers = user->emm_data->emm_timers; int rc; /* Increment the retransmission counter */ - _emm_detach_data.count += 1; + emm_detach_data->count += 1; LOG_TRACE(WARNING, "EMM-PROC - T3421 timer expired, " - "retransmission counter = %d", _emm_detach_data.count); + "retransmission counter = %d", emm_detach_data->count); - if (_emm_detach_data.count < EMM_DETACH_COUNTER_MAX) { + if (emm_detach_data->count < EMM_DETACH_COUNTER_MAX) { /* Retransmit the Detach Request message */ emm_sap_t emm_sap; emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data; /* Stop timer T3421 */ - T3421.id = nas_timer_stop(T3421.id); + emm_timers->T3421.id = nas_timer_stop(emm_timers->T3421.id); /* Setup NAS information message to transfer */ emm_as->NASinfo = EMM_AS_NAS_INFO_DETACH; emm_as->NASmsg.length = 0; emm_as->NASmsg.value = NULL; /* Set the detach type */ - emm_as->type = _emm_detach_data.type; + emm_as->type = emm_detach_data->type; /* Set the switch-off indicator */ - emm_as->switch_off = _emm_detach_data.switch_off; + emm_as->switch_off = emm_detach_data->switch_off; /* Set the EPS mobile identity */ - emm_as->guti = _emm_data.guti; - emm_as->ueid = 0; + emm_as->guti = user->emm_data->guti; + emm_as->ueid = user->ueid; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_as->sctx, _emm_data.security, + emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, FALSE, TRUE); /* @@ -419,17 +412,17 @@ void *_emm_detach_t3421_handler(void *args) * be sent to the network */ emm_sap.primitive = EMMAS_DATA_REQ; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Start T3421 timer */ - T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL); + emm_timers->T3421.id = nas_timer_start(emm_timers->T3421.sec, emm_detach_t3421_handler, user); LOG_TRACE(INFO, "EMM-PROC - Timer T3421 (%d) expires in %ld " - "seconds", T3421.id, T3421.sec); + "seconds", emm_timers->T3421.id, emm_timers->T3421.sec); } } else { /* Abort the detach procedure */ - rc = _emm_detach_abort(_emm_detach_data.type); + rc = _emm_detach_abort(user, emm_detach_data->type); } LOG_FUNC_RETURN(NULL); @@ -448,34 +441,34 @@ void *_emm_detach_t3421_handler(void *args) ** Description: Aborts the detach procedure ** ** ** ** Inputs: type: not used ** - ** Others: _emm_detach_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: T3421 ** ** ** ***************************************************************************/ -static int _emm_detach_abort(emm_proc_detach_type_t type) +static int _emm_detach_abort(nas_user_t *user, emm_proc_detach_type_t type) { LOG_FUNC_IN; + emm_timers_t *emm_timers = user->emm_data->emm_timers; emm_sap_t emm_sap; int rc ; LOG_TRACE(WARNING, "EMM-PROC - Abort the detach procedure"); /* Reset EMM procedure handler */ - (void) emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); /* Stop timer T3421 */ - T3421.id = nas_timer_stop(T3421.id); + emm_timers->T3421.id = nas_timer_stop(emm_timers->T3421.id); /* * Notify EMM that detach procedure failed */ emm_sap.primitive = EMMREG_DETACH_FAILED; emm_sap.u.emm_reg.u.detach.type = type; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/EMM/EmmStatusHdl.c b/openair3/NAS/UE/EMM/EmmStatusHdl.c index c95441d37065e316a7869185860c98be8babfe48..89dd50207f05b80d454de9899d54434f255d6499 100644 --- a/openair3/NAS/UE/EMM/EmmStatusHdl.c +++ b/openair3/NAS/UE/EMM/EmmStatusHdl.c @@ -115,7 +115,7 @@ int emm_proc_status_ind(unsigned int ueid, int emm_cause) ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_status(unsigned int ueid, int emm_cause) +int emm_proc_status(nas_user_t *user, int emm_cause) { LOG_FUNC_IN; @@ -132,15 +132,15 @@ int emm_proc_status(unsigned int ueid, int emm_cause) */ emm_sap.primitive = EMMAS_STATUS_IND; emm_sap.u.emm_as.u.status.emm_cause = emm_cause; - emm_sap.u.emm_as.u.status.ueid = ueid; + emm_sap.u.emm_as.u.status.ueid = user->ueid; - emm_sap.u.emm_as.u.status.guti = _emm_data.guti; - sctx = _emm_data.security; + emm_sap.u.emm_as.u.status.guti = user->emm_data->guti; + sctx = user->emm_data->security; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.status.sctx, sctx, FALSE, TRUE); - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/EMM/Identification.c b/openair3/NAS/UE/EMM/Identification.c index a9ceb7a43bd522669c23ede0ab31fe74f8a8f871..7cf2e765c61322a185618566632227270f083e6f 100644 --- a/openair3/NAS/UE/EMM/Identification.c +++ b/openair3/NAS/UE/EMM/Identification.c @@ -49,6 +49,7 @@ Description Defines the identification EMM procedure executed by the #include "emm_sap.h" #include "msc.h" +#include "user_defs.h" #include <stdlib.h> // malloc, free #include <string.h> // memcpy @@ -102,7 +103,7 @@ static const char *_emm_identity_type_str[] = { ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_identification_request(emm_proc_identity_type_t type) +int emm_proc_identification_request(nas_user_t *user, emm_proc_identity_type_t type) { LOG_FUNC_IN; @@ -114,7 +115,7 @@ int emm_proc_identification_request(emm_proc_identity_type_t type) /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ - rc = emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); if (rc != RETURNok) { LOG_TRACE(WARNING, @@ -129,8 +130,8 @@ int emm_proc_identification_request(emm_proc_identity_type_t type) imsi_t modified_imsi; /* International Mobile Subscriber Identity is requested */ - if (_emm_data.imsi) { - memcpy (&modified_imsi, _emm_data.imsi, sizeof (modified_imsi)); + if (user->emm_data->imsi) { + memcpy (&modified_imsi, user->emm_data->imsi, sizeof (modified_imsi)); /* LW: Eventually replace the 0xF value set in MNC digit 3 by a 0 to avoid IMSI to be truncated before reaching HSS */ if (modified_imsi.u.num.digit6 == 0xF) { @@ -166,9 +167,9 @@ int emm_proc_identification_request(emm_proc_identity_type_t type) case EMM_IDENT_TYPE_IMEI: /* International Mobile Equipment Identity is requested */ - if (_emm_data.imei) { + if (user->emm_data->imei) { emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_IMEI; - emm_sap.u.emm_as.u.security.imei = _emm_data.imei; + emm_sap.u.emm_as.u.security.imei = user->emm_data->imei; } break; @@ -176,9 +177,9 @@ int emm_proc_identification_request(emm_proc_identity_type_t type) case EMM_IDENT_TYPE_TMSI: /* Temporary Mobile Subscriber Identity is requested */ - if (_emm_data.guti) { + if (user->emm_data->guti) { emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_TMSI; - emm_sap.u.emm_as.u.security.tmsi = _emm_data.guti->m_tmsi; + emm_sap.u.emm_as.u.security.tmsi = user->emm_data->guti->m_tmsi; } break; @@ -193,13 +194,13 @@ int emm_proc_identification_request(emm_proc_identity_type_t type) * to the MME */ emm_sap.primitive = EMMAS_SECURITY_RES; - emm_sap.u.emm_as.u.security.guti = _emm_data.guti; - emm_sap.u.emm_as.u.security.ueid = 0; + emm_sap.u.emm_as.u.security.guti = user->emm_data->guti; + emm_sap.u.emm_as.u.security.ueid = user->ueid; emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_IDENT; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - _emm_data.security, FALSE, TRUE); - rc = emm_sap_send(&emm_sap); + user->emm_data->security, FALSE, TRUE); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/EMM/IdleMode.c b/openair3/NAS/UE/EMM/IdleMode.c index a5a2c3070894305392cc2ef0b760f49837d1f9b6..159a3b2a2ceba18bd0e76c2d32d1494f72b36a29 100644 --- a/openair3/NAS/UE/EMM/IdleMode.c +++ b/openair3/NAS/UE/EMM/IdleMode.c @@ -59,6 +59,7 @@ Description Defines EMM procedures executed by the Non-Access Stratum #include "emm_proc.h" #include "nas_log.h" +#include "utils.h" #include "emm_sap.h" @@ -78,56 +79,8 @@ Description Defines EMM procedures executed by the Non-Access Stratum /****************************************************************************/ static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn); -static int _IldlMode_get_opnn_id(const plmn_t *plmn); -static int _IdleMode_get_suitable_cell(int index); - -/* - * A list of PLMN identities in priority order is maintained locally - * to perform the PLMN selection procedure. - * - * In automatic mode of operation, this list is used for PLMN selection when - * the UE is switched on, or upon recovery from lack of coverage, or when the - * user requests the UE to initiate PLMN reselection, and registration. - * In manual mode of operation, this list is displayed to the user that may - * select an available PLMN and initiate registration. - * - * The list may contain PLMN identifiers in the following order: - * - The last registered PLMN or each equivalent PLMN present in the list of - * "equivalent PLMNs" (EPLMN_MAX), when UE is switched on or following - * recovery from lack of coverage; - * - The highest priority PLMN in the list of "equivalent HPLMNs" or the - * HPLMN derived from the IMSI (1) - * - Each PLMN/access technology combination in the "User Controlled PLMN - * Selector with Access Technology" (PLMN_MAX) - * - Each PLMN/access technology combination in the "Operator Controlled PLMN - * Selector with Access Technology" (OPLMN_MAX) - * - Other PLMN/access technology combinations with received high quality - * signal in random order (TODO) - * - Other PLMN/access technology combinations in order of decreasing signal - * quality (TODO) - * - The last selected PLMN again (1) - */ -static struct { - int n_plmns; -#define EMM_PLMN_LIST_SIZE (EMM_DATA_EPLMN_MAX + EMM_DATA_PLMN_MAX + \ - EMM_DATA_OPLMN_MAX + 2) - plmn_t *plmn[EMM_PLMN_LIST_SIZE]; - int index; /* Index of the PLMN for which selection is ongoing */ - int hplmn; /* Index of the home PLMN or the highest priority - * equivalent home PLMN */ - int fplmn; /* Index of the first forbidden PLMN */ - int splmn; /* Index of the currently selected PLMN */ - int rplmn; /* Index of the currently registered PLMN */ - struct plmn_param_t { - char fullname[NET_FORMAT_LONG_SIZE+1]; /* PLMN full identifier */ - char shortname[NET_FORMAT_SHORT_SIZE+1]; /* PLMN short identifier */ - char num[NET_FORMAT_NUM_SIZE+1]; /* PLMN numeric identifier */ - int stat; /* Indication of the PLMN availability */ - int tac; /* Location/Tracking Area Code */ - int ci; /* Serving cell identifier */ - int rat; /* Radio Access Technology supported by the serving cell */ - } param[EMM_PLMN_LIST_SIZE]; -} _emm_plmn_list; +static int _IldlMode_get_opnn_id(emm_data_t *emm_data, const plmn_t *plmn); +static int _IdleMode_get_suitable_cell(nas_user_t *user, int index); /* Callback executed whenever a network indication is received */ static IdleMode_callback_t _emm_indication_notify; @@ -152,21 +105,23 @@ static IdleMode_callback_t _emm_indication_notify; ** Others: _emm_plmn_list, _emm_indication_notify ** ** ** ***************************************************************************/ -void IdleMode_initialize(IdleMode_callback_t cb) +void IdleMode_initialize(nas_user_t *user, IdleMode_callback_t cb) { + emm_plmn_list_t *emm_plmn_list = calloc_or_fail( sizeof(emm_plmn_list_t)); + user->emm_plmn_list = emm_plmn_list; /* Initialize the list of available PLMNs */ - _emm_plmn_list.n_plmns = 0; - _emm_plmn_list.index = 0; - _emm_plmn_list.hplmn = -1; - _emm_plmn_list.fplmn = -1; - _emm_plmn_list.splmn = -1; - _emm_plmn_list.rplmn = -1; + emm_plmn_list->n_plmns = 0; + emm_plmn_list->index = 0; + emm_plmn_list->hplmn = -1; + emm_plmn_list->fplmn = -1; + emm_plmn_list->splmn = -1; + emm_plmn_list->rplmn = -1; /* Initialize the network notification handler */ _emm_indication_notify = *cb; /* Initialize EMM Service Access Point */ - emm_sap_initialize(); + emm_sap_initialize(user); } /* @@ -190,9 +145,9 @@ void IdleMode_initialize(IdleMode_callback_t cb) ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_nb_plmns(void) +int IdleMode_get_nb_plmns(emm_plmn_list_t *emm_plmn_list) { - return _emm_plmn_list.n_plmns; + return emm_plmn_list->n_plmns; } /**************************************************************************** @@ -211,9 +166,9 @@ int IdleMode_get_nb_plmns(void) ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_hplmn_index(void) +int IdleMode_get_hplmn_index(emm_plmn_list_t *emm_plmn_list) { - return _emm_plmn_list.hplmn; + return emm_plmn_list->hplmn; } /**************************************************************************** @@ -232,9 +187,9 @@ int IdleMode_get_hplmn_index(void) ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_rplmn_index(void) +int IdleMode_get_rplmn_index(emm_plmn_list_t *emm_plmn_list) { - return _emm_plmn_list.rplmn; + return emm_plmn_list->rplmn; } /**************************************************************************** @@ -245,16 +200,15 @@ int IdleMode_get_rplmn_index(void) ** available PLMNs. ** ** ** ** Inputs: None ** - ** Others: _emm_plmn_list ** ** ** ** Outputs: None ** ** Return: The index of the selected PLMN in the list ** ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_splmn_index(void) +int IdleMode_get_splmn_index(emm_plmn_list_t *emm_plmn_list) { - return _emm_plmn_list.splmn; + return emm_plmn_list->splmn; } /**************************************************************************** @@ -265,38 +219,36 @@ int IdleMode_get_splmn_index(void) ** tors present in the network ** ** ** ** Inputs: i: Index of the first operator to update ** - ** Others: _emm_plmn_list ** ** ** ** Outputs: None ** ** Return: The size of the list in bytes ** - ** Others: _emm_data.plist ** ** ** ***************************************************************************/ -int IdleMode_update_plmn_list(int i) +int IdleMode_update_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, int i) { int offset = 0; int n = 1; - while ( (i < _emm_plmn_list.n_plmns) && (offset < EMM_DATA_BUFFER_SIZE) ) { - struct plmn_param_t *plmn = &(_emm_plmn_list.param[i++]); + while ( (i < emm_plmn_list->n_plmns) && (offset < EMM_DATA_BUFFER_SIZE) ) { + struct plmn_param_t *plmn = &(emm_plmn_list->param[i++]); if (n++ > 1) { - offset += snprintf(_emm_data.plist.buffer + offset, + offset += snprintf(emm_data->plist.buffer + offset, EMM_DATA_BUFFER_SIZE - offset, ","); } - offset += snprintf(_emm_data.plist.buffer + offset, + offset += snprintf(emm_data->plist.buffer + offset, EMM_DATA_BUFFER_SIZE - offset, "(%d,%s,%s,%s", plmn->stat, plmn->fullname, plmn->shortname, plmn->num); if (plmn->rat != NET_ACCESS_UNAVAILABLE) { - offset += snprintf(_emm_data.plist.buffer + offset, + offset += snprintf(emm_data->plist.buffer + offset, EMM_DATA_BUFFER_SIZE - offset, ",%d", plmn->rat); } - offset += snprintf(_emm_data.plist.buffer + offset, + offset += snprintf(emm_data->plist.buffer + offset, EMM_DATA_BUFFER_SIZE - offset, ")"); } @@ -320,13 +272,13 @@ int IdleMode_update_plmn_list(int i) ** Others: None ** ** ** ***************************************************************************/ -const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index, +const char *IdleMode_get_plmn_fullname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len) { - if (index < _emm_plmn_list.n_plmns) { - assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) ); - *len = strlen(_emm_plmn_list.param[index].fullname); - return _emm_plmn_list.param[index].fullname; + if (index < emm_plmn_list->n_plmns) { + assert( PLMNS_ARE_EQUAL(*plmn, *emm_plmn_list->plmn[index]) ); + *len = strlen(emm_plmn_list->param[index].fullname); + return emm_plmn_list->param[index].fullname; } return NULL; @@ -349,13 +301,13 @@ const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index, ** Others: None ** ** ** ***************************************************************************/ -const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index, +const char *IdleMode_get_plmn_shortname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len) { - if (index < _emm_plmn_list.n_plmns) { - assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) ); - *len = strlen(_emm_plmn_list.param[index].shortname); - return _emm_plmn_list.param[index].shortname; + if (index < emm_plmn_list->n_plmns) { + assert( PLMNS_ARE_EQUAL(*plmn, *emm_plmn_list->plmn[index]) ); + *len = strlen(emm_plmn_list->param[index].shortname); + return emm_plmn_list->param[index].shortname; } return NULL; @@ -379,12 +331,12 @@ const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index, ** Others: None ** ** ** ***************************************************************************/ -const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len) +const char *IdleMode_get_plmn_id(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len) { - if (index < _emm_plmn_list.n_plmns) { - assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) ); - *len = strlen(_emm_plmn_list.param[index].num); - return _emm_plmn_list.param[index].num; + if (index < emm_plmn_list->n_plmns) { + assert( PLMNS_ARE_EQUAL(*plmn, *emm_plmn_list->plmn[index]) ); + *len = strlen(emm_plmn_list->param[index].num); + return emm_plmn_list->param[index].num; } return NULL; @@ -406,13 +358,13 @@ const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len) ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_plmn_fullname_index(const char *plmn) +int IdleMode_get_plmn_fullname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn) { int index; /* Get the index of the PLMN identifier with specified full name */ - for (index = 0; index < _emm_plmn_list.n_plmns; index++) { - if ( strncmp(plmn, _emm_plmn_list.param[index].fullname, + for (index = 0; index < emm_plmn_list->n_plmns; index++) { + if ( strncmp(plmn, emm_plmn_list->param[index].fullname, NET_FORMAT_LONG_SIZE) != 0 ) { continue; } @@ -439,13 +391,13 @@ int IdleMode_get_plmn_fullname_index(const char *plmn) ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_plmn_shortname_index(const char *plmn) +int IdleMode_get_plmn_shortname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn) { int index; /* Get the index of the PLMN identifier with specified short name */ - for (index = 0; index < _emm_plmn_list.n_plmns; index++) { - if ( !strncmp(plmn, _emm_plmn_list.param[index].shortname, + for (index = 0; index < emm_plmn_list->n_plmns; index++) { + if ( !strncmp(plmn, emm_plmn_list->param[index].shortname, NET_FORMAT_SHORT_SIZE) ) { continue; } @@ -472,13 +424,13 @@ int IdleMode_get_plmn_shortname_index(const char *plmn) ** Others: None ** ** ** ***************************************************************************/ -int IdleMode_get_plmn_id_index(const char *plmn) +int IdleMode_get_plmn_id_index(emm_plmn_list_t *emm_plmn_list, const char *plmn) { int index; /* Get the index of the PLMN identifier with specified numeric identifier */ - for (index = 0; index < _emm_plmn_list.n_plmns; index++) { - if ( !strncmp(plmn, _emm_plmn_list.param[index].num, + for (index = 0; index < emm_plmn_list->n_plmns; index++) { + if ( !strncmp(plmn, emm_plmn_list->param[index].num, NET_FORMAT_LONG_SIZE) ) { continue; } @@ -503,66 +455,67 @@ int IdleMode_get_plmn_id_index(const char *plmn) ** to PLMN selection procedure. ** ** ** ** Inputs: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: _emm_plmn_list ** ** ** ***************************************************************************/ -int emm_proc_initialize(void) +int emm_proc_initialize(nas_user_t *user) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc; int i; + emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list; - if (!_emm_data.usim_is_valid) { + if (!user->emm_data->usim_is_valid) { /* The USIM application is not present or not valid */ LOG_TRACE(WARNING, "EMM-IDLE - USIM is not valid"); emm_sap.primitive = EMMREG_NO_IMSI; } else { /* The highest priority is given to either the "equivalent PLMNs" * if available, or the last registered PLMN */ - if (_emm_data.nvdata.eplmn.n_plmns > 0) { - for (i=0; i < _emm_data.nvdata.eplmn.n_plmns; i++) { - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = - &_emm_data.nvdata.eplmn.plmn[i]; + if (user->emm_data->nvdata.eplmn.n_plmns > 0) { + for (i=0; i < user->emm_data->nvdata.eplmn.n_plmns; i++) { + emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = + &user->emm_data->nvdata.eplmn.plmn[i]; } - } else if ( PLMN_IS_VALID(_emm_data.nvdata.rplmn) ) { - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = - &_emm_data.nvdata.rplmn; + } else if ( PLMN_IS_VALID(user->emm_data->nvdata.rplmn) ) { + emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = + &user->emm_data->nvdata.rplmn; } /* Update the index of the HPLMN or EHPLM of highest priority. * When switched on, the UE will try to automatically register * to each previous PLMN within the ordered list of available * PLMNs regardless of the network selection mode of operation */ - _emm_plmn_list.hplmn = _emm_plmn_list.n_plmns - 1; - // LG_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns; + emm_plmn_list->hplmn = emm_plmn_list->n_plmns - 1; + // LGemm_plmn_list->hplmn = emm_plmn_list->n_plmns; /* Add the highest priority PLMN in the list of "equivalent HPLMNs" if present and not empty, or the HPLMN derived from the IMSI */ - if (_emm_data.ehplmn.n_plmns > 0) { - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = - &_emm_data.ehplmn.plmn[0]; + if (user->emm_data->ehplmn.n_plmns > 0) { + emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = + &user->emm_data->ehplmn.plmn[0]; } else { - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = &_emm_data.hplmn; + emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = &user->emm_data->hplmn; } /* Each PLMN/access technology combination in the "User * Controlled PLMN Selector with Access Technology" */ - for (i=0; i < _emm_data.plmn.n_plmns; i++) { - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = - &_emm_data.plmn.plmn[i]; + for (i=0; i < user->emm_data->plmn.n_plmns; i++) { + emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = + &user->emm_data->plmn.plmn[i]; } /* Each PLMN/access technology combination in the "Operator * Controlled PLMN Selector with Access Technology" */ - for (i=0; i < _emm_data.oplmn.n_plmns; i++) { - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = - &_emm_data.oplmn.plmn[i]; + for (i=0; i < user->emm_data->oplmn.n_plmns; i++) { + emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = + &user->emm_data->oplmn.plmn[i]; } /* Other PLMN/access technology combinations with received @@ -574,21 +527,21 @@ int emm_proc_initialize(void) /* TODO: Schedule periodic network selection attemps (hpplmn timer) */ /* Initialize the PLMNs' parameters */ - for (i=0; i < _emm_plmn_list.n_plmns; i++) { - struct plmn_param_t *plmn = &(_emm_plmn_list.param[i]); - int id = _IldlMode_get_opnn_id(_emm_plmn_list.plmn[i]); + for (i=0; i < emm_plmn_list->n_plmns; i++) { + struct plmn_param_t *plmn = &(emm_plmn_list->param[i]); + int id = _IldlMode_get_opnn_id(user->emm_data, emm_plmn_list->plmn[i]); if (id < 0) { plmn->fullname[0] = '\0'; plmn->shortname[0] = '\0'; } else { - strncpy(plmn->fullname, _emm_data.opnn[id].fullname, + strncpy(plmn->fullname, user->emm_data->opnn[id].fullname, NET_FORMAT_LONG_SIZE); - strncpy(plmn->shortname, _emm_data.opnn[id].shortname, + strncpy(plmn->shortname, user->emm_data->opnn[id].shortname, NET_FORMAT_SHORT_SIZE); } - (void)_IdleMode_plmn_str(plmn->num, _emm_plmn_list.plmn[i]); + (void)_IdleMode_plmn_str(plmn->num, emm_plmn_list->plmn[i]); plmn->stat = NET_OPER_UNKNOWN; plmn->tac = 0; plmn->ci = 0; @@ -596,14 +549,14 @@ int emm_proc_initialize(void) } LOG_TRACE(INFO, "EMM-IDLE - %d PLMNs available for network selection", - _emm_plmn_list.n_plmns); + emm_plmn_list->n_plmns); /* Notify EMM that PLMN selection procedure has to be executed */ emm_sap.primitive = EMMREG_REGISTER_REQ; emm_sap.u.emm_reg.u.regist.index = 0; } - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN(rc); @@ -627,35 +580,38 @@ int emm_proc_initialize(void) ** mode. ** ** ** ** Inputs: None ** - ** Others: _emm_plmn_list, _emm_data ** + ** Others: _emm_plmn_list, user->emm_data-> ** ** ** ** Outputs: None ** ** Return: None ** - ** Others: _emm_plmn_list.index ** + ** Others: emm_plmn_list->index ** ** ** ***************************************************************************/ -int emm_proc_plmn_selection(int index) +int emm_proc_plmn_selection(nas_user_t *user, int index) { LOG_FUNC_IN; + emm_data_t *emm_data = user->emm_data; + user_api_id_t *user_api_id = user->user_api_id; + emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list; int rc = RETURNok; - if (_emm_data.plmn_mode != EMM_DATA_PLMN_AUTO) { + if (emm_data->plmn_mode != EMM_DATA_PLMN_AUTO) { /* * Manual or manual/automatic mode of operation * -------------------------------------------- */ - if (index >= _emm_plmn_list.hplmn) { + if (index >= emm_plmn_list->hplmn) { /* * Selection of the last registered or equivalent PLMNs failed */ - if (_emm_data.plmn_index < 0) { + if (emm_data->plmn_index < 0) { /* * The user did not select any PLMN yet; display the ordered * list of available PLMNs to the user */ index = -1; - rc = emm_proc_network_notify(_emm_plmn_list.hplmn); + rc = emm_proc_network_notify(emm_plmn_list, user_api_id, emm_data, emm_plmn_list->hplmn); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-IDLE - Failed to notify " @@ -665,7 +621,7 @@ int emm_proc_plmn_selection(int index) /* * Try to register to the PLMN manually selected by the user */ - index = _emm_data.plmn_index; + index = emm_data->plmn_index; } } } @@ -678,8 +634,8 @@ int emm_proc_plmn_selection(int index) * or any other PLMN in the ordered list of available PLMNs in * automatic mode. */ - _emm_plmn_list.index = index; - rc = _IdleMode_get_suitable_cell(index); + emm_plmn_list->index = index; + rc = _IdleMode_get_suitable_cell(user, index); } LOG_FUNC_RETURN (rc); @@ -714,47 +670,48 @@ int emm_proc_plmn_selection(int index) ** ci: The identifier of the cell ** ** rat: The radio access technology supported by ** ** the cell ** - ** Others: _emm_plmn_list, _emm_data ** ** ** ** Outputs: None ** ** Return: None ** - ** Others: _emm_plmn_list, _emm_data ** ** ** ***************************************************************************/ -int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) +int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t rat) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc = RETURNerror; - int index = _emm_plmn_list.index; + emm_data_t *emm_data = user->emm_data; + emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list; + user_api_id_t *user_api_id = user->user_api_id; + int index = emm_plmn_list->index; int select_next_plmn = FALSE; LOG_TRACE(INFO, "EMM-IDLE - %s cell found for PLMN %d in %s mode", (found)? "One" : "No", index, - (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" : - (_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" : + (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" : + (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" : "Automatic/manual"); if (found) { int is_forbidden = FALSE; /* Select the PLMN of which a suitable cell has been found */ - _emm_data.splmn = *_emm_plmn_list.plmn[index]; + emm_data->splmn = *emm_plmn_list->plmn[index]; /* Update the selected PLMN's parameters */ - _emm_plmn_list.param[index].tac = tac; - _emm_plmn_list.param[index].ci = ci; - _emm_plmn_list.param[index].rat = rat; + emm_plmn_list->param[index].tac = tac; + emm_plmn_list->param[index].ci = ci; + emm_plmn_list->param[index].rat = rat; /* Update the location data and notify EMM that data have changed */ - rc = emm_proc_location_notify(tac, ci , rat); + rc = emm_proc_location_notify(user_api_id, emm_data, tac, ci , rat); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-IDLE - Failed to notify location update"); } - if (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO) { + if (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO) { /* * Automatic mode of operation * --------------------------- @@ -762,17 +719,17 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) int i; /* Check if the selected PLMN is in the forbidden list */ - for (i = 0; i < _emm_data.fplmn.n_plmns; i++) { - if (PLMNS_ARE_EQUAL(_emm_data.splmn, _emm_data.fplmn.plmn[i])) { + for (i = 0; i < emm_data->fplmn.n_plmns; i++) { + if (PLMNS_ARE_EQUAL(emm_data->splmn, emm_data->fplmn.plmn[i])) { is_forbidden = TRUE; break; } } if (!is_forbidden) { - for (i = 0; i < _emm_data.fplmn_gprs.n_plmns; i++) { - if (PLMNS_ARE_EQUAL(_emm_data.splmn, - _emm_data.fplmn_gprs.plmn[i])) { + for (i = 0; i < emm_data->fplmn_gprs.n_plmns; i++) { + if (PLMNS_ARE_EQUAL(emm_data->splmn, + emm_data->fplmn_gprs.plmn[i])) { is_forbidden = TRUE; break; } @@ -782,12 +739,12 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) /* Check if the selected PLMN belongs to a forbidden * tracking area */ tai_t tai; - tai.plmn = _emm_data.splmn; + tai.plmn = emm_data->splmn; tai.tac = tac; if (!is_forbidden) { - for (i = 0; i < _emm_data.ftai.n_tais; i++) { - if (TAIS_ARE_EQUAL(tai, _emm_data.ftai.tai[i])) { + for (i = 0; i < emm_data->ftai.n_tais; i++) { + if (TAIS_ARE_EQUAL(tai, emm_data->ftai.tai[i])) { is_forbidden = TRUE; break; } @@ -795,8 +752,8 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) } if (!is_forbidden) { - for (i = 0; i < _emm_data.ftai_roaming.n_tais; i++) { - if (TAIS_ARE_EQUAL(tai, _emm_data.ftai_roaming.tai[i])) { + for (i = 0; i < emm_data->ftai_roaming.n_tais; i++) { + if (TAIS_ARE_EQUAL(tai, emm_data->ftai_roaming.tai[i])) { is_forbidden = TRUE; break; } @@ -810,25 +767,25 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) LOG_TRACE(INFO, "EMM-IDLE - UE may camp on this acceptable cell for limited services"); /* Save the index of the first forbidden PLMN */ - if (_emm_plmn_list.fplmn < 0) { - _emm_plmn_list.fplmn = index; + if (emm_plmn_list->fplmn < 0) { + emm_plmn_list->fplmn = index; } - _emm_plmn_list.param[index].stat = NET_OPER_FORBIDDEN; + emm_plmn_list->param[index].stat = NET_OPER_FORBIDDEN; } else { /* A suitable cell has been found and the PLMN or tracking area * is not in the forbidden list */ LOG_TRACE(INFO, "EMM-IDLE - UE may camp on this suitable cell for normal services"); - _emm_plmn_list.fplmn = -1; - _emm_plmn_list.param[index].stat = NET_OPER_CURRENT; + emm_plmn_list->fplmn = -1; + emm_plmn_list->param[index].stat = NET_OPER_CURRENT; emm_sap.primitive = EMMREG_REGISTER_CNF; } /* Duplicate the new selected PLMN at the end of the ordered list */ - _emm_plmn_list.plmn[_emm_plmn_list.n_plmns] = &_emm_data.splmn; + emm_plmn_list->plmn[emm_plmn_list->n_plmns] = &emm_data->splmn; } - else if (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO) { + else if (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO) { /* * Automatic mode of operation * --------------------------- @@ -839,12 +796,12 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) select_next_plmn = TRUE; /* Bypass the previously selected PLMN */ - if (index == _emm_plmn_list.splmn) { + if (index == emm_plmn_list->splmn) { index += 1; } } - else if (_emm_data.plmn_index < 0) { + else if (emm_data->plmn_index < 0) { /* * Manual or manual/automatic mode of operation * -------------------------------------------- @@ -855,7 +812,7 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) select_next_plmn = TRUE; } - else if (_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL) { + else if (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL) { /* * Manual mode of operation * ------------------------ @@ -871,8 +828,8 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) * Attempt to find a suitable cell of the PLMN selected by the user * failed; Try to automatically select another PLMN */ - _emm_data.plmn_mode = EMM_DATA_PLMN_AUTO; - index = _emm_plmn_list.hplmn; + emm_data->plmn_mode = EMM_DATA_PLMN_AUTO; + index = emm_plmn_list->hplmn; select_next_plmn = TRUE; } @@ -880,17 +837,17 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) * Force an attempt to register to the next PLMN */ if (select_next_plmn) { - int last_plmn_index = _emm_plmn_list.n_plmns; + int last_plmn_index = emm_plmn_list->n_plmns; - if (_emm_plmn_list.splmn != -1) { + if (emm_plmn_list->splmn != -1) { /* The last attempt was to register the previously selected PLMN */ last_plmn_index += 1; } if (index < last_plmn_index) { /* Try to select the next PLMN in the list of available PLMNs */ - _emm_plmn_list.index = index; - rc = emm_proc_plmn_selection(index); + emm_plmn_list->index = index; + rc = emm_proc_plmn_selection(user, index); } else { /* No suitable cell of any PLMN within the ordered list * of available PLMNs has been found */ @@ -903,46 +860,43 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) * Or terminate the PLMN selection procedure */ if (!select_next_plmn) { - /* TODO: be sure of this fix */ - LOG_TRACE(WARNING, "%s:%d:%s: be sure!!\n", __FILE__, __LINE__, __FUNCTION__); - //if (!(_emm_plmn_list.fplmn) < 0) { // FIXME this comparison makes no sense (bool < 0) - if (!(_emm_plmn_list.fplmn < 0)) { // FIXME this comparison makes no sense (bool < 0) + if (emm_plmn_list->fplmn >= 0) { /* There were one or more PLMNs which were available and allowable, * but an LR failure made registration on those PLMNs unsuccessful * or an entry in any of the forbidden area lists prevented a * registration attempt; select the first such PLMN and enters a * limited service state. */ - index = _emm_plmn_list.fplmn; - _emm_plmn_list.fplmn = -1; + index = emm_plmn_list->fplmn; + emm_plmn_list->fplmn = -1; emm_sap.primitive = EMMREG_REGISTER_REJ; } /* Update the availability indicator of the previously selected PLMN */ - if (_emm_plmn_list.splmn != -1) { - _emm_plmn_list.param[_emm_plmn_list.splmn].stat = NET_OPER_UNKNOWN; + if (emm_plmn_list->splmn != -1) { + emm_plmn_list->param[emm_plmn_list->splmn].stat = NET_OPER_UNKNOWN; } /* Update the index of the new selected PLMN */ if (emm_sap.primitive != EMMREG_NO_CELL) { - _emm_plmn_list.splmn = index; + emm_plmn_list->splmn = index; } else { - _emm_plmn_list.splmn = -1; + emm_plmn_list->splmn = -1; } /* * Notify EMM that PLMN selection procedure has completed */ - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); - if (_emm_plmn_list.splmn != -1) { - if (_emm_plmn_list.splmn == _emm_plmn_list.rplmn) { + if (emm_plmn_list->splmn != -1) { + if (emm_plmn_list->splmn == emm_plmn_list->rplmn) { /* The selected PLMN is the registered PLMN */ LOG_TRACE(INFO, "EMM-IDLE - The selected PLMN is the registered PLMN"); - _emm_data.is_rplmn = TRUE; - } else if (_emm_plmn_list.splmn < _emm_plmn_list.hplmn) { + emm_data->is_rplmn = TRUE; + } else if (emm_plmn_list->splmn < emm_plmn_list->hplmn) { /* The selected PLMN is in the list of equivalent PLMNs */ LOG_TRACE(INFO, "EMM-IDLE - The selected PLMN is in the list of equivalent PLMNs"); - _emm_data.is_eplmn = TRUE; + emm_data->is_eplmn = TRUE; } /* @@ -950,7 +904,7 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) * to register the presence of the UE to the selected PLMN */ emm_sap.primitive = EMMREG_ATTACH_INIT; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } } @@ -976,20 +930,20 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -int emm_proc_registration_notify(Stat_t status) +int emm_proc_registration_notify(user_api_id_t *user_api_id, emm_data_t *emm_data, Stat_t status) { LOG_FUNC_IN; int rc = RETURNok; /* Update the network registration status */ - if (_emm_data.stat != status) { - _emm_data.stat = status; + if (emm_data->stat != status) { + emm_data->stat = status; /* Notify EMM that data has changed */ - rc = (*_emm_indication_notify)(1); + rc = (*_emm_indication_notify)(user_api_id, emm_data, 1); } LOG_FUNC_RETURN (rc); @@ -1010,24 +964,24 @@ int emm_proc_registration_notify(Stat_t status) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -int emm_proc_location_notify(tac_t tac, ci_t ci, AcT_t rat) +int emm_proc_location_notify(user_api_id_t *user_api_id, emm_data_t *emm_data, tac_t tac, ci_t ci, AcT_t rat) { LOG_FUNC_IN; int rc = RETURNok; /* Update the location information */ - if ( (_emm_data.tac != tac) || - (_emm_data.ci != ci) || - (_emm_data.rat != rat) ) { - _emm_data.tac = tac; - _emm_data.ci = ci; - _emm_data.rat = rat; + if ( (emm_data->tac != tac) || + (emm_data->ci != ci) || + (emm_data->rat != rat) ) { + emm_data->tac = tac; + emm_data->ci = ci; + emm_data->rat = rat; /* Notify EMM that data has changed */ - rc = (*_emm_indication_notify)(0); + rc = (*_emm_indication_notify)(user_api_id, emm_data, 0); } LOG_FUNC_RETURN (rc); @@ -1047,17 +1001,17 @@ int emm_proc_location_notify(tac_t tac, ci_t ci, AcT_t rat) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -int emm_proc_network_notify(int index) +int emm_proc_network_notify(emm_plmn_list_t *emm_plmn_list, user_api_id_t *user_api_id, emm_data_t *emm_data, int index) { LOG_FUNC_IN; /* Update the list of operators present in the network */ - int size = IdleMode_update_plmn_list(index); + int size = IdleMode_update_plmn_list(emm_plmn_list, emm_data, index); /* Notify EMM that data has changed */ - int rc = (*_emm_indication_notify)(size); + int rc = (*_emm_indication_notify)(user_api_id, emm_data, size); LOG_FUNC_RETURN (rc); } @@ -1126,7 +1080,6 @@ static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn) ** tor network name records ** ** ** ** Inputs: plmn: The PLMN identifier ** - ** Others: _emm_data ** ** ** ** Outputs: None ** ** Return: The index of the PLMN if found in the list ** @@ -1135,32 +1088,32 @@ static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn) ** Others: None ** ** ** ***************************************************************************/ -static int _IldlMode_get_opnn_id(const plmn_t *plmn) +static int _IldlMode_get_opnn_id(emm_data_t *emm_data, const plmn_t *plmn) { int i; - for (i = 0; i < _emm_data.n_opnns; i++) { - if (plmn->MCCdigit1 != _emm_data.opnn[i].plmn->MCCdigit1) { + for (i = 0; i < emm_data->n_opnns; i++) { + if (plmn->MCCdigit1 != emm_data->opnn[i].plmn->MCCdigit1) { continue; } - if (plmn->MCCdigit2 != _emm_data.opnn[i].plmn->MCCdigit2) { + if (plmn->MCCdigit2 != emm_data->opnn[i].plmn->MCCdigit2) { continue; } - if (plmn->MCCdigit3 != _emm_data.opnn[i].plmn->MCCdigit3) { + if (plmn->MCCdigit3 != emm_data->opnn[i].plmn->MCCdigit3) { continue; } - if (plmn->MNCdigit1 != _emm_data.opnn[i].plmn->MNCdigit1) { + if (plmn->MNCdigit1 != emm_data->opnn[i].plmn->MNCdigit1) { continue; } - if (plmn->MNCdigit2 != _emm_data.opnn[i].plmn->MNCdigit2) { + if (plmn->MNCdigit2 != emm_data->opnn[i].plmn->MNCdigit2) { continue; } - if (plmn->MNCdigit3 != _emm_data.opnn[i].plmn->MNCdigit3) { + if (plmn->MNCdigit3 != emm_data->opnn[i].plmn->MNCdigit3) { continue; } @@ -1181,22 +1134,23 @@ static int _IldlMode_get_opnn_id(const plmn_t *plmn) ** ** ** Inputs: index: Index of the selected PLMN in the ordered ** ** list of available PLMNs ** - ** Others: _emm_plmn_list.plmn ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ -static int _IdleMode_get_suitable_cell(int index) +static int _IdleMode_get_suitable_cell(nas_user_t *user, int index) { emm_sap_t emm_sap; - const plmn_t *plmn = _emm_plmn_list.plmn[index]; + emm_data_t *emm_data = user->emm_data; + emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list; + const plmn_t *plmn = emm_plmn_list->plmn[index]; LOG_TRACE(INFO, "EMM-IDLE - Trying to search a suitable cell " "of PLMN %d in %s mode", index, - (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" : - (_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" : + (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" : + (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" : "Automatic/manual"); /* * Notify EMM-AS SAP that cell information related to the given @@ -1206,12 +1160,12 @@ static int _IdleMode_get_suitable_cell(int index) emm_sap.u.emm_as.u.cell_info.plmnIDs.n_plmns = 1; emm_sap.u.emm_as.u.cell_info.plmnIDs.plmn[0] = *plmn; - if (_emm_data.plmn_rat != NET_ACCESS_UNAVAILABLE) { - emm_sap.u.emm_as.u.cell_info.rat = (1 << _emm_data.plmn_rat); + if (emm_data->plmn_rat != NET_ACCESS_UNAVAILABLE) { + emm_sap.u.emm_as.u.cell_info.rat = (1 << emm_data->plmn_rat); } else { emm_sap.u.emm_as.u.cell_info.rat = NET_ACCESS_UNAVAILABLE; } - return emm_sap_send(&emm_sap); + return emm_sap_send(user, &emm_sap); } diff --git a/openair3/NAS/UE/EMM/IdleMode.h b/openair3/NAS/UE/EMM/IdleMode.h index f75d149e911c049cab88a17bd7b991c216a2d4f3..e80b4f91344931edd7117917a33ed5d38150f068 100644 --- a/openair3/NAS/UE/EMM/IdleMode.h +++ b/openair3/NAS/UE/EMM/IdleMode.h @@ -41,6 +41,7 @@ Description Defines the functions used to get information from the list #define __IDLEMODE_H__ #include "commonDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -50,7 +51,7 @@ Description Defines the functions used to get information from the list /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ -typedef int (*IdleMode_callback_t) (int); +typedef int (*IdleMode_callback_t) (user_api_id_t *user_api_id, emm_data_t *emm_data, int); /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ @@ -60,23 +61,23 @@ typedef int (*IdleMode_callback_t) (int); /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void IdleMode_initialize(IdleMode_callback_t cb); +void IdleMode_initialize(nas_user_t *user, IdleMode_callback_t cb); -int IdleMode_get_nb_plmns(void); -int IdleMode_get_hplmn_index(void); -int IdleMode_get_rplmn_index(void); -int IdleMode_get_splmn_index(void); +int IdleMode_get_nb_plmns(emm_plmn_list_t *emm_plmn_list); +int IdleMode_get_hplmn_index(emm_plmn_list_t *emm_plmn_list); +int IdleMode_get_rplmn_index(emm_plmn_list_t *emm_plmn_list); +int IdleMode_get_splmn_index(emm_plmn_list_t *emm_plmn_list); -int IdleMode_update_plmn_list(int index); +int IdleMode_update_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, int i); -const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index, +const char *IdleMode_get_plmn_fullname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len); -const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index, +const char *IdleMode_get_plmn_shortname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len); -const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len); +const char *IdleMode_get_plmn_id(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len); -int IdleMode_get_plmn_fullname_index(const char *plmn); -int IdleMode_get_plmn_shortname_index(const char *plmn); -int IdleMode_get_plmn_id_index(const char *plmn); +int IdleMode_get_plmn_fullname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn); +int IdleMode_get_plmn_shortname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn); +int IdleMode_get_plmn_id_index(emm_plmn_list_t *emm_plmn_list, const char *plmn); #endif /* __IDLEMODE_H__*/ diff --git a/openair3/NAS/UE/EMM/IdleMode_defs.h b/openair3/NAS/UE/EMM/IdleMode_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..8ef6c8e86d407ec9813537f8c88745438a51fa94 --- /dev/null +++ b/openair3/NAS/UE/EMM/IdleMode_defs.h @@ -0,0 +1,52 @@ +#ifndef _IDLEMODE_DEFS_H +#define _IDLEMODE_DEFS_H + +/* + * A list of PLMN identities in priority order is maintained locally + * to perform the PLMN selection procedure. + * + * In automatic mode of operation, this list is used for PLMN selection when + * the UE is switched on, or upon recovery from lack of coverage, or when the + * user requests the UE to initiate PLMN reselection, and registration. + * In manual mode of operation, this list is displayed to the user that may + * select an available PLMN and initiate registration. + * + * The list may contain PLMN identifiers in the following order: + * - The last registered PLMN or each equivalent PLMN present in the list of + * "equivalent PLMNs" (EPLMN_MAX), when UE is switched on or following + * recovery from lack of coverage; + * - The highest priority PLMN in the list of "equivalent HPLMNs" or the + * HPLMN derived from the IMSI (1) + * - Each PLMN/access technology combination in the "User Controlled PLMN + * Selector with Access Technology" (PLMN_MAX) + * - Each PLMN/access technology combination in the "Operator Controlled PLMN + * Selector with Access Technology" (OPLMN_MAX) + * - Other PLMN/access technology combinations with received high quality + * signal in random order (TODO) + * - Other PLMN/access technology combinations in order of decreasing signal + * quality (TODO) + * - The last selected PLMN again (1) + */ +typedef struct { + int n_plmns; +#define EMM_PLMN_LIST_SIZE (EMM_DATA_EPLMN_MAX + EMM_DATA_PLMN_MAX + \ + EMM_DATA_OPLMN_MAX + 2) + plmn_t *plmn[EMM_PLMN_LIST_SIZE]; + int index; /* Index of the PLMN for which selection is ongoing */ + int hplmn; /* Index of the home PLMN or the highest priority + * equivalent home PLMN */ + int fplmn; /* Index of the first forbidden PLMN */ + int splmn; /* Index of the currently selected PLMN */ + int rplmn; /* Index of the currently registered PLMN */ + struct plmn_param_t { + char fullname[NET_FORMAT_LONG_SIZE+1]; /* PLMN full identifier */ + char shortname[NET_FORMAT_SHORT_SIZE+1]; /* PLMN short identifier */ + char num[NET_FORMAT_NUM_SIZE+1]; /* PLMN numeric identifier */ + int stat; /* Indication of the PLMN availability */ + int tac; /* Location/Tracking Area Code */ + int ci; /* Serving cell identifier */ + int rat; /* Radio Access Technology supported by the serving cell */ + } param[EMM_PLMN_LIST_SIZE]; +} emm_plmn_list_t; + +#endif diff --git a/openair3/NAS/UE/EMM/LowerLayer.c b/openair3/NAS/UE/EMM/LowerLayer.c index f0f7a3c5b6a42d84b1eb6d6d8257d01628e2fb6a..b5555b2c2fa13b68a0180b3ede87474666662869 100644 --- a/openair3/NAS/UE/EMM/LowerLayer.c +++ b/openair3/NAS/UE/EMM/LowerLayer.c @@ -60,17 +60,6 @@ Description Defines EMM procedures executed by the Non-Access Stratum /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ -/* - * Data structure used to handle EMM procedures executed by the UE upon - * receiving lower layer notifications - */ -static struct { - lowerlayer_success_callback_t success; /* Successful data delivery */ - lowerlayer_failure_callback_t failure; /* Lower layer failure */ - lowerlayer_release_callback_t release; /* NAS signalling release */ - void *args; /* EMM procedure argument parameters */ -} _lowerlayer_data; - /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ @@ -88,7 +77,6 @@ static struct { ** Description: Notify the EPS Mobility Management entity that data have ** ** been successfully delivered to the network ** ** ** - ** Inputs: ueid: UE lower layer identifier ** ** Others: None ** ** ** ** Outputs: None ** @@ -96,7 +84,7 @@ static struct { ** Others: None ** ** ** ***************************************************************************/ -int lowerlayer_success(unsigned int ueid) +int lowerlayer_success(nas_user_t *user) { LOG_FUNC_IN; @@ -104,8 +92,8 @@ int lowerlayer_success(unsigned int ueid) int rc; emm_sap.primitive = EMMREG_LOWERLAYER_SUCCESS; - emm_sap.u.emm_reg.ueid = ueid; - rc = emm_sap_send(&emm_sap); + emm_sap.u.emm_reg.ueid = user->ueid; + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -117,7 +105,6 @@ int lowerlayer_success(unsigned int ueid) ** Description: Notify the EPS Mobility Management entity that lower la- ** ** yers failed to deliver data to the network ** ** ** - ** Inputs: ueid: UE lower layer identifier ** ** Others: None ** ** ** ** Outputs: None ** @@ -125,7 +112,7 @@ int lowerlayer_success(unsigned int ueid) ** Others: None ** ** ** ***************************************************************************/ -int lowerlayer_failure(unsigned int ueid) +int lowerlayer_failure(nas_user_t *user) { LOG_FUNC_IN; @@ -133,8 +120,8 @@ int lowerlayer_failure(unsigned int ueid) int rc; emm_sap.primitive = EMMREG_LOWERLAYER_FAILURE; - emm_sap.u.emm_reg.ueid = ueid; - rc = emm_sap_send(&emm_sap); + emm_sap.u.emm_reg.ueid = user->ueid; + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -155,12 +142,12 @@ int lowerlayer_failure(unsigned int ueid) ** Others: None ** ** ** ***************************************************************************/ -int lowerlayer_establish(void) +int lowerlayer_establish(nas_user_t *user) { LOG_FUNC_IN; /* Update the EPS Connection Management status */ - _emm_data.ecm_status = ECM_CONNECTED; + user->emm_data->ecm_status = ECM_CONNECTED; LOG_FUNC_RETURN (RETURNok); } @@ -180,7 +167,7 @@ int lowerlayer_establish(void) ** Others: None ** ** ** ***************************************************************************/ -int lowerlayer_release(int cause) +int lowerlayer_release(nas_user_t *user, int cause) { LOG_FUNC_IN; @@ -188,11 +175,11 @@ int lowerlayer_release(int cause) int rc; /* Update the EPS Connection Management status */ - _emm_data.ecm_status = ECM_IDLE; + user->emm_data->ecm_status = ECM_IDLE; emm_sap.primitive = EMMREG_LOWERLAYER_RELEASE; - emm_sap.u.emm_reg.ueid = 0; - rc = emm_sap_send(&emm_sap); + emm_sap.u.emm_reg.ueid = user->ueid; + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -204,7 +191,6 @@ int lowerlayer_release(int cause) ** Description: Notify the EPS Session Management entity that data have ** ** been received from lower layers ** ** ** - ** Inputs: ueid: UE lower layer identifier ** ** data: Data transfered from lower layers ** ** Others: None ** ** ** @@ -213,7 +199,7 @@ int lowerlayer_release(int cause) ** Others: None ** ** ** ***************************************************************************/ -int lowerlayer_data_ind(unsigned int ueid, const OctetString *data) +int lowerlayer_data_ind(nas_user_t *user, const OctetString *data) { esm_sap_t esm_sap; int rc; @@ -223,10 +209,10 @@ int lowerlayer_data_ind(unsigned int ueid, const OctetString *data) esm_sap.primitive = ESM_UNITDATA_IND; esm_sap.is_standalone = TRUE; - esm_sap.ueid = ueid; + esm_sap.ueid = user->ueid; esm_sap.recv = data; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); LOG_FUNC_RETURN (rc); } @@ -238,7 +224,6 @@ int lowerlayer_data_ind(unsigned int ueid, const OctetString *data) ** Description: Notify the EPS Mobility Management entity that data have ** ** to be transfered to lower layers ** ** ** - ** Inputs: ueid: UE lower layer identifier ** ** data: Data to be transfered to lower layers ** ** Others: None ** ** ** @@ -247,7 +232,7 @@ int lowerlayer_data_ind(unsigned int ueid, const OctetString *data) ** Others: None ** ** ** ***************************************************************************/ -int lowerlayer_data_req(unsigned int ueid, const OctetString *data) +int lowerlayer_data_req(nas_user_t *user, const OctetString *data) { LOG_FUNC_IN; @@ -257,16 +242,16 @@ int lowerlayer_data_req(unsigned int ueid, const OctetString *data) //struct emm_data_context_s *ctx = NULL; emm_sap.primitive = EMMAS_DATA_REQ; - emm_sap.u.emm_as.u.data.guti = _emm_data.guti; - emm_sap.u.emm_as.u.data.ueid = 0; - sctx = _emm_data.security; + emm_sap.u.emm_as.u.data.guti = user->emm_data->guti; + emm_sap.u.emm_as.u.data.ueid = user->ueid; + sctx = user->emm_data->security; emm_sap.u.emm_as.u.data.NASinfo = 0; emm_sap.u.emm_as.u.data.NASmsg.length = data->length; emm_sap.u.emm_as.u.data.NASmsg.value = data->value; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, sctx, FALSE, TRUE); - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -297,17 +282,17 @@ int lowerlayer_data_req(unsigned int ueid, const OctetString *data) ** Others: _lowerlayer_data ** ** ** ***************************************************************************/ -int emm_proc_lowerlayer_initialize(lowerlayer_success_callback_t success, +int emm_proc_lowerlayer_initialize(lowerlayer_data_t *lowerlayer_data, lowerlayer_success_callback_t success, lowerlayer_failure_callback_t failure, lowerlayer_release_callback_t release, void *args) { LOG_FUNC_IN; - _lowerlayer_data.success = success; - _lowerlayer_data.failure = failure; - _lowerlayer_data.release = release; - _lowerlayer_data.args = args; + lowerlayer_data->success = success; + lowerlayer_data->failure = failure; + lowerlayer_data->release = release; + lowerlayer_data->args = args; LOG_FUNC_RETURN (RETURNok); } @@ -328,17 +313,17 @@ int emm_proc_lowerlayer_initialize(lowerlayer_success_callback_t success, ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_lowerlayer_success(void) +int emm_proc_lowerlayer_success(lowerlayer_data_t *lowerlayer_data) { LOG_FUNC_IN; int rc = RETURNok; - lowerlayer_success_callback_t emm_callback = _lowerlayer_data.success; + lowerlayer_success_callback_t emm_callback = lowerlayer_data->success; if (emm_callback) { - rc = (*emm_callback)(_lowerlayer_data.args); - _lowerlayer_data.success = NULL; + rc = (*emm_callback)(lowerlayer_data->args); + lowerlayer_data->success = NULL; } LOG_FUNC_RETURN (rc); @@ -360,17 +345,17 @@ int emm_proc_lowerlayer_success(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_lowerlayer_failure(int is_initial) +int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, int is_initial) { LOG_FUNC_IN; int rc = RETURNok; - lowerlayer_failure_callback_t emm_callback = _lowerlayer_data.failure; + lowerlayer_failure_callback_t emm_callback = lowerlayer_data->failure; if (emm_callback) { - rc = (*emm_callback)(is_initial, _lowerlayer_data.args); - _lowerlayer_data.failure = NULL; + rc = (*emm_callback)(is_initial, lowerlayer_data->args); + lowerlayer_data->failure = NULL; } LOG_FUNC_RETURN (rc); @@ -391,17 +376,17 @@ int emm_proc_lowerlayer_failure(int is_initial) ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_lowerlayer_release(void) +int emm_proc_lowerlayer_release(lowerlayer_data_t *lowerlayer_data) { LOG_FUNC_IN; int rc = RETURNok; - lowerlayer_release_callback_t emm_callback = _lowerlayer_data.release; + lowerlayer_release_callback_t emm_callback = lowerlayer_data->release; if (emm_callback) { - rc = (*emm_callback)(_lowerlayer_data.args); - _lowerlayer_data.release = NULL; + rc = (*emm_callback)(lowerlayer_data->args); + lowerlayer_data->release = NULL; } LOG_FUNC_RETURN (rc); diff --git a/openair3/NAS/UE/EMM/LowerLayer.h b/openair3/NAS/UE/EMM/LowerLayer.h index 396de203d3da340565542069053262d16595d088..00e271feaa7e9c0dd3e3426401b6dd75c589f5e7 100644 --- a/openair3/NAS/UE/EMM/LowerLayer.h +++ b/openair3/NAS/UE/EMM/LowerLayer.h @@ -43,33 +43,17 @@ Description Defines EMM procedures executed by the Non-Access Stratum #define __LOWERLAYER_H__ #include "OctetString.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ -/* - * Type of EMM procedure callback function executed whenever data are - * successfully delivered to the network - */ -typedef int (*lowerlayer_success_callback_t)(void *); - -/* - * Type of EMM procedure callback function executed when data are not - * delivered to the network because a lower layer failure occurred - */ -typedef int (*lowerlayer_failure_callback_t)(int, void *); - -/* - * Type of EMM procedure callback function executed when NAS signalling - * connection is released - */ -typedef int (*lowerlayer_release_callback_t)(void *); - /****************************************************************************/ /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ + /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ @@ -78,12 +62,26 @@ typedef int (*lowerlayer_release_callback_t)(void *); /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int lowerlayer_success(unsigned int ueid); -int lowerlayer_failure(unsigned int ueid); -int lowerlayer_establish(void); -int lowerlayer_release(int cause); - -int lowerlayer_data_ind(unsigned int ueid, const OctetString *data); -int lowerlayer_data_req(unsigned int ueid, const OctetString *data); +/* + *--------------------------------------------------------------------------- + * Lower layer procedure + *--------------------------------------------------------------------------- + */ +int emm_proc_lowerlayer_initialize(lowerlayer_data_t *lowerlayer_data, lowerlayer_success_callback_t success, + lowerlayer_failure_callback_t failure, + lowerlayer_release_callback_t release, + void *args); +int emm_proc_lowerlayer_success(lowerlayer_data_t *lowerlayer_data); +int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, int is_initial); +int emm_proc_lowerlayer_release(lowerlayer_data_t *lowerlayer_data); + + +int lowerlayer_success(nas_user_t *user); +int lowerlayer_failure(nas_user_t *user); +int lowerlayer_establish(nas_user_t *user); +int lowerlayer_release(nas_user_t *user, int cause); + +int lowerlayer_data_ind(nas_user_t *user, const OctetString *data); +int lowerlayer_data_req(nas_user_t *user, const OctetString *data); #endif /* __LOWERLAYER_H__*/ diff --git a/openair3/NAS/UE/EMM/LowerLayer_defs.h b/openair3/NAS/UE/EMM/LowerLayer_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..6035d4ed12db9111ef0bd75e7f81a550c4e58018 --- /dev/null +++ b/openair3/NAS/UE/EMM/LowerLayer_defs.h @@ -0,0 +1,33 @@ +#ifndef _LOWER_LAYER_DEFS_H +#define _LOWER_LAYER_DEFS_H + +/* + * Type of EMM procedure callback function executed whenever data are + * successfully delivered to the network + */ +typedef int (*lowerlayer_success_callback_t)(void *); + +/* + * Type of EMM procedure callback function executed when data are not + * delivered to the network because a lower layer failure occurred + */ +typedef int (*lowerlayer_failure_callback_t)(int, void *); + +/* + * Type of EMM procedure callback function executed when NAS signalling + * connection is released + */ +typedef int (*lowerlayer_release_callback_t)(void *); + +/* + * Data structure used to handle EMM procedures executed by the UE upon + * receiving lower layer notifications + */ +typedef struct { + lowerlayer_success_callback_t success; /* Successful data delivery */ + lowerlayer_failure_callback_t failure; /* Lower layer failure */ + lowerlayer_release_callback_t release; /* NAS signalling release */ + void *args; /* EMM procedure argument parameters */ +} lowerlayer_data_t; + +#endif diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregistered.c b/openair3/NAS/UE/EMM/SAP/EmmDeregistered.c index 801de96145d1ec4ec58271e0a5d13888086ba322..a2a93c4d780a68e36c6b97ee3a7c3eb0ee64d8b5 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregistered.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregistered.c @@ -54,6 +54,7 @@ Description Implements the EPS Mobility Management procedures executed #include "nas_log.h" #include "emm_proc.h" +#include "user_defs.h" #include <assert.h> @@ -86,17 +87,17 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregistered(const emm_reg_t *evt) +int EmmDeregistered(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_DEREGISTERED); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED); /* Delete the authentication data RAND and RES */ - rc = emm_proc_authentication_delete(); + rc = emm_proc_authentication_delete(user); if (rc != RETURNok) { LOG_FUNC_RETURN (rc); @@ -116,7 +117,7 @@ int EmmDeregistered(const emm_reg_t *evt) /* * The UE was powered on without a valid USIM application present */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_NO_IMSI); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NO_IMSI); break; case _EMMREG_REGISTER_REQ: @@ -124,11 +125,11 @@ int EmmDeregistered(const emm_reg_t *evt) * The default EMM primary substate when the UE is switched on * with valid USIM application shall be PLMN-SEARCH */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_PLMN_SEARCH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_PLMN_SEARCH); if (rc != RETURNerror) { /* Process the network registration request */ - rc = emm_fsm_process(evt); + rc = emm_fsm_process(user, evt); } break; @@ -142,14 +143,14 @@ int EmmDeregistered(const emm_reg_t *evt) /* Move to the corresponding initial EMM state */ if (evt->u.attach.is_emergency) { - rc = emm_fsm_set_status(EMM_DEREGISTERED_LIMITED_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_LIMITED_SERVICE); } else { - rc = emm_fsm_set_status(EMM_DEREGISTERED_NORMAL_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NORMAL_SERVICE); } if (rc != RETURNerror) { /* Restart the attach procedure */ - rc = emm_proc_attach_restart(); + rc = emm_proc_attach_restart(user); } break; diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttachNeeded.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttachNeeded.c index 4f8cbc862bbc08ca30733660d13da0cfd77f7a0f..cbdc470a0b844d996fcef9c23626a5543734ec87 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttachNeeded.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttachNeeded.c @@ -47,6 +47,7 @@ Description Implements the EPS Mobility Management procedures executed #include "emm_fsm.h" #include "commonDef.h" #include "nas_log.h" +#include "user_defs.h" #include <assert.h> @@ -77,11 +78,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredAttachNeeded(const emm_reg_t *evt) +int EmmDeregisteredAttachNeeded(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_ATTACH_NEEDED); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_ATTACH_NEEDED); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c index ed1d079930a467611dd9420306d366944330d3fc..7ddfac03db225bfc34cb83c093dcff0f121f911d 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c @@ -79,13 +79,13 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredAttemptingToAttach(const emm_reg_t *evt) +int EmmDeregisteredAttemptingToAttach(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH); switch (evt->primitive) { case _EMMREG_ATTACH_INIT: @@ -97,14 +97,14 @@ int EmmDeregisteredAttemptingToAttach(const emm_reg_t *evt) /* Move to the corresponding initial EMM state */ if (evt->u.attach.is_emergency) { - rc = emm_fsm_set_status(EMM_DEREGISTERED_LIMITED_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_LIMITED_SERVICE); } else { - rc = emm_fsm_set_status(EMM_DEREGISTERED_NORMAL_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NORMAL_SERVICE); } if (rc != RETURNerror) { /* Restart the attach procedure */ - rc = emm_proc_attach_restart(); + rc = emm_proc_attach_restart(user); } break; @@ -113,14 +113,14 @@ int EmmDeregisteredAttemptingToAttach(const emm_reg_t *evt) /* * Data successfully delivered to the network */ - rc = emm_proc_lowerlayer_success(); + rc = emm_proc_lowerlayer_success(user->lowerlayer_data); break; case _EMMREG_LOWERLAYER_FAILURE: /* * Data failed to be delivered to the network */ - rc = emm_proc_lowerlayer_failure(FALSE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, FALSE); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredInitiated.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredInitiated.c index 220e666aa7d91a35c5417d42b2ac684d714426ab..d18b66a3162bc876043d649d78804973400aab6b 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredInitiated.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredInitiated.c @@ -78,13 +78,13 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredInitiated(const emm_reg_t *evt) +int EmmDeregisteredInitiated(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_INITIATED); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_INITIATED); switch (evt->primitive) { @@ -94,7 +94,7 @@ int EmmDeregisteredInitiated(const emm_reg_t *evt) * bearer contexts have been deactivated as UE initiated * detach procedure successfully completed) */ - rc = emm_fsm_set_status(EMM_DEREGISTERED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED); break; case _EMMREG_DETACH_FAILED: @@ -103,9 +103,9 @@ int EmmDeregisteredInitiated(const emm_reg_t *evt) * The detach procedure failed */ if (evt->u.detach.type == EMM_DETACH_TYPE_IMSI) { - rc = emm_fsm_set_status(EMM_REGISTERED_NORMAL_SERVICE); + rc = emm_fsm_set_status(user, EMM_REGISTERED_NORMAL_SERVICE); } else { - rc = emm_fsm_set_status(EMM_DEREGISTERED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED); } break; @@ -123,7 +123,8 @@ int EmmDeregisteredInitiated(const emm_reg_t *evt) * Lower layer failure or release of the NAS signalling connection * before the Detach Accept is received */ - rc = emm_proc_lowerlayer_release(); + // FIXME review + rc = emm_proc_lowerlayer_release(user->lowerlayer_data); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c index 78d418c69c57653b8727693e7e813b9649f182af..394325441597f64991cedf81764e4408caaae0c9 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c @@ -83,24 +83,24 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredLimitedService(const emm_reg_t *evt) +int EmmDeregisteredLimitedService(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_LIMITED_SERVICE); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_LIMITED_SERVICE); switch (evt->primitive) { case _EMMREG_REGISTER_REQ: /* * The user manually re-selected a PLMN to register to */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_PLMN_SEARCH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_PLMN_SEARCH); if (rc != RETURNerror) { /* Process the network registration request */ - rc = emm_fsm_process(evt); + rc = emm_fsm_process(user, evt); } break; @@ -109,7 +109,7 @@ int EmmDeregisteredLimitedService(const emm_reg_t *evt) /* * Initiate attach procedure for emergency bearer services */ - rc = emm_proc_attach(EMM_ATTACH_TYPE_EMERGENCY); + rc = emm_proc_attach(user, EMM_ATTACH_TYPE_EMERGENCY); break; case _EMMREG_ATTACH_REQ: @@ -118,7 +118,7 @@ int EmmDeregisteredLimitedService(const emm_reg_t *evt) * (Attach Request message successfully delivered to the network); * enter state EMM-REGISTERED-INITIATED */ - rc = emm_fsm_set_status(EMM_REGISTERED_INITIATED); + rc = emm_fsm_set_status(user, EMM_REGISTERED_INITIATED); break; case _EMMREG_LOWERLAYER_SUCCESS: @@ -126,21 +126,21 @@ int EmmDeregisteredLimitedService(const emm_reg_t *evt) * Initial NAS message has been successfully delivered * to the network */ - rc = emm_proc_lowerlayer_success(); + rc = emm_proc_lowerlayer_success(user->lowerlayer_data); break; case _EMMREG_LOWERLAYER_FAILURE: /* * Initial NAS message failed to be delivered to the network */ - rc = emm_proc_lowerlayer_failure(TRUE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, TRUE); break; case _EMMREG_LOWERLAYER_RELEASE: /* * NAS signalling connection has been released */ - rc = emm_proc_lowerlayer_release(); + rc = emm_proc_lowerlayer_release(user->lowerlayer_data); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c index 9f1f526e83f4dff12002c1c8eef0e8b2862c7494..af9ab5e5be773ccd0090a9986d506139bfe365be 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c @@ -84,13 +84,15 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredNoCellAvailable(const emm_reg_t *evt) +int EmmDeregisteredNoCellAvailable(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; + emm_data_t *emm_data = user->emm_data; + user_api_id_t *user_api_id = user->user_api_id; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_NO_CELL_AVAILABLE); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_NO_CELL_AVAILABLE); switch (evt->primitive) { /* TODO: network re-selection is not allowed when in No Cell @@ -101,14 +103,14 @@ int EmmDeregisteredNoCellAvailable(const emm_reg_t *evt) /* * The user manually re-selected a PLMN to register to */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_PLMN_SEARCH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_PLMN_SEARCH); if (rc != RETURNerror) { /* * Notify EMM that the MT is currently searching an operator * to register to */ - rc = emm_proc_registration_notify(NET_REG_STATE_ON); + rc = emm_proc_registration_notify(user_api_id, emm_data, NET_REG_STATE_ON); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-FSM - " @@ -118,7 +120,7 @@ int EmmDeregisteredNoCellAvailable(const emm_reg_t *evt) /* * Perform network re-selection procedure */ - rc = emm_proc_plmn_selection(evt->u.regist.index); + rc = emm_proc_plmn_selection(user, evt->u.regist.index); } break; diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoImsi.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoImsi.c index 059c1f551ba6d955cce108f09285172821e9ea59..0f883c8109d3990939b755bdec22698dbe1013d5 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoImsi.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNoImsi.c @@ -78,11 +78,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredNoImsi(const emm_reg_t *evt) +int EmmDeregisteredNoImsi(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_NO_IMSI); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_NO_IMSI); LOG_TRACE(ERROR, "EMM-FSM - USIM is not present or not valid"); diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c index 85f98c4bd7b03e40e093b37d3c86827f1c21fe82..3ec7a96ba8ab416ff73ba3f2ac2bfa332a369a70 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c @@ -84,24 +84,24 @@ extern uint8_t usim_test; ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredNormalService(const emm_reg_t *evt) +int EmmDeregisteredNormalService(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_NORMAL_SERVICE); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_NORMAL_SERVICE); switch (evt->primitive) { case _EMMREG_REGISTER_REQ: /* * The user manually re-selected a PLMN to register to */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_PLMN_SEARCH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_PLMN_SEARCH); if (rc != RETURNerror) { /* Process the network registration request */ - rc = emm_fsm_process(evt); + rc = emm_fsm_process(user, evt); } break; @@ -112,11 +112,11 @@ int EmmDeregisteredNormalService(const emm_reg_t *evt) */ if(usim_test == 0) { - rc = emm_proc_attach(EMM_ATTACH_TYPE_EPS); + rc = emm_proc_attach(user, EMM_ATTACH_TYPE_EPS); } else { - rc = emm_proc_attach(EMM_ATTACH_TYPE_IMSI); // CMW500 IMSI initial attach expected + rc = emm_proc_attach(user, EMM_ATTACH_TYPE_IMSI); // CMW500 IMSI initial attach expected } break; @@ -126,7 +126,7 @@ int EmmDeregisteredNormalService(const emm_reg_t *evt) * message successfully delivered to the network); * enter state EMM-REGISTERED-INITIATED */ - rc = emm_fsm_set_status(EMM_REGISTERED_INITIATED); + rc = emm_fsm_set_status(user, EMM_REGISTERED_INITIATED); break; case _EMMREG_LOWERLAYER_SUCCESS: @@ -134,21 +134,21 @@ int EmmDeregisteredNormalService(const emm_reg_t *evt) * Initial NAS message has been successfully delivered * to the network */ - rc = emm_proc_lowerlayer_success(); + rc = emm_proc_lowerlayer_success(user->lowerlayer_data); break; case _EMMREG_LOWERLAYER_FAILURE: /* * Initial NAS message failed to be delivered to the network */ - rc = emm_proc_lowerlayer_failure(TRUE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, TRUE); break; case _EMMREG_LOWERLAYER_RELEASE: /* * NAS signalling connection has been released */ - rc = emm_proc_lowerlayer_release(); + rc = emm_proc_lowerlayer_release(user->lowerlayer_data); break; case _EMMREG_ATTACH_CNF: @@ -157,7 +157,7 @@ int EmmDeregisteredNormalService(const emm_reg_t *evt) * context activated; * enter state EMM-REGISTERED. */ - rc = emm_fsm_set_status(EMM_REGISTERED); + rc = emm_fsm_set_status(user, EMM_REGISTERED); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredPlmnSearch.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredPlmnSearch.c index d9865c9b720bf53334fa486b7eedf135c2966a0c..ed41362f2f900563e5776fe2847408cab369b93b 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredPlmnSearch.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredPlmnSearch.c @@ -82,27 +82,29 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmDeregisteredPlmnSearch(const emm_reg_t *evt) +int EmmDeregisteredPlmnSearch(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; + emm_data_t *emm_data = user->emm_data; + user_api_id_t *user_api_id = user->user_api_id; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_DEREGISTERED_PLMN_SEARCH); + assert(emm_fsm_get_status(user) == EMM_DEREGISTERED_PLMN_SEARCH); switch (evt->primitive) { case _EMMREG_NO_CELL: /* * No suitable cell of the selected PLMN has been found to camp on */ - rc = emm_proc_registration_notify(NET_REG_STATE_DENIED); + rc = emm_proc_registration_notify(user_api_id, emm_data, NET_REG_STATE_DENIED); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-FSM - " "Failed to notify registration update"); } - rc = emm_fsm_set_status(EMM_DEREGISTERED_NO_CELL_AVAILABLE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NO_CELL_AVAILABLE); break; case _EMMREG_REGISTER_REQ: @@ -112,7 +114,7 @@ int EmmDeregisteredPlmnSearch(const emm_reg_t *evt) * may be selected either automatically or manually. * Or the user manually re-selected a PLMN to register to. */ - rc = emm_proc_registration_notify(NET_REG_STATE_ON); + rc = emm_proc_registration_notify(user_api_id, emm_data, NET_REG_STATE_ON); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-FSM - " @@ -122,7 +124,7 @@ int EmmDeregisteredPlmnSearch(const emm_reg_t *evt) /* * Perform network selection procedure */ - rc = emm_proc_plmn_selection(evt->u.regist.index); + rc = emm_proc_plmn_selection(user, evt->u.regist.index); break; case _EMMREG_REGISTER_REJ: @@ -130,14 +132,14 @@ int EmmDeregisteredPlmnSearch(const emm_reg_t *evt) * The selected cell is known not to be able to provide normal * service */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_LIMITED_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_LIMITED_SERVICE); break; case _EMMREG_REGISTER_CNF: /* * A suitable cell of the selected PLMN has been found to camp on */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_NORMAL_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NORMAL_SERVICE); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmNull.c b/openair3/NAS/UE/EMM/SAP/EmmNull.c index e482281a7184974a9604ec7a0f42d85912eb57dc..7b553f0a765474bc97e405d6c5d591874cdf0a2e 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmNull.c +++ b/openair3/NAS/UE/EMM/SAP/EmmNull.c @@ -46,6 +46,7 @@ Description Implements the EPS Mobility Management procedures executed #include "nas_log.h" #include "emm_proc.h" +#include "user_defs.h" #include <assert.h> @@ -76,16 +77,16 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmNull(const emm_reg_t *evt) +int EmmNull(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc; - assert(emm_fsm_get_status() == EMM_NULL); + assert(emm_fsm_get_status(user) == EMM_NULL); /* Delete the authentication data RAND and RES */ - rc = emm_proc_authentication_delete(); + rc = emm_proc_authentication_delete(user); if (rc != RETURNok) { LOG_FUNC_RETURN (rc); @@ -97,14 +98,14 @@ int EmmNull(const emm_reg_t *evt) * The EPS capability has been enabled in the UE: * Move to the DEREGISTERED state; */ - rc = emm_fsm_set_status(EMM_DEREGISTERED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED); /* * And initialize the EMM procedure call manager in order to * establish an EMM context and make the UE reachable by an MME. */ if (rc != RETURNerror) { - rc = emm_proc_initialize(); + rc = emm_proc_initialize(user); } break; diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegistered.c b/openair3/NAS/UE/EMM/SAP/EmmRegistered.c index dcbeee167eb8c3cabaec7fa3c15b369e7905df46..dbc51e51554382af949dee6bd1c6116e334d5186 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegistered.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegistered.c @@ -81,13 +81,13 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegistered(const emm_reg_t *evt) +int EmmRegistered(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; - assert(emm_fsm_get_status() == EMM_REGISTERED); + assert(emm_fsm_get_status(user) == EMM_REGISTERED); switch (evt->primitive) { @@ -96,7 +96,7 @@ int EmmRegistered(const emm_reg_t *evt) /* * Initiate detach procedure for EPS services */ - rc = emm_proc_detach(EMM_DETACH_TYPE_EPS, evt->u.detach.switch_off); + rc = emm_proc_detach(user, EMM_DETACH_TYPE_EPS, evt->u.detach.switch_off); break; case _EMMREG_DETACH_REQ: @@ -105,7 +105,7 @@ int EmmRegistered(const emm_reg_t *evt) * message successfully delivered to the network); * enter state EMM-DEREGISTERED-INITIATED */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_INITIATED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_INITIATED); break; case _EMMREG_DETACH_CNF: @@ -113,7 +113,7 @@ int EmmRegistered(const emm_reg_t *evt) * The UE implicitly detached from the network (all EPS * bearer contexts may have been deactivated) */ - rc = emm_fsm_set_status(EMM_DEREGISTERED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED); break; case _EMMREG_TAU_REQ: @@ -136,21 +136,21 @@ int EmmRegistered(const emm_reg_t *evt) /* * Data transfer message has been successfully delivered */ - rc = emm_proc_lowerlayer_success(); + rc = emm_proc_lowerlayer_success(user->lowerlayer_data); break; case _EMMREG_LOWERLAYER_FAILURE: /* * Data transfer message failed to be delivered */ - rc = emm_proc_lowerlayer_failure(FALSE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, FALSE); break; case _EMMREG_LOWERLAYER_RELEASE: /* * NAS signalling connection has been released */ - rc = emm_proc_lowerlayer_release(); + rc = emm_proc_lowerlayer_release(user->lowerlayer_data); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c index 59d8f45df9a195a37f35115e5cfef6bac5fe05bd..21654123d1462e3deeba854f5790acc9398e68a4 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c @@ -78,11 +78,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredAttemptingToUpdate(const emm_reg_t *evt) +int EmmRegisteredAttemptingToUpdate(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_ATTEMPTING_TO_UPDATE); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_ATTEMPTING_TO_UPDATE); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c index c522d5ec5cc0c84e31aba3b8c66bd74f2129e378..6855843a25bbe01ba70e58913ada26d0d12983d1 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c @@ -78,11 +78,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredImsiDetachInitiated(const emm_reg_t *evt) +int EmmRegisteredImsiDetachInitiated(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_IMSI_DETACH_INITIATED); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_IMSI_DETACH_INITIATED); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c index 688b168b5318025aac0b049c7f825731c4bce5c0..d10f0d1053c0c939408600b85fc8c5a2424ce0dc 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c @@ -78,13 +78,15 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredInitiated(const emm_reg_t *evt) +int EmmRegisteredInitiated(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; int rc = RETURNerror; + emm_data_t *emm_data = user->emm_data; + user_api_id_t *user_api_id = user->user_api_id; - assert(emm_fsm_get_status() == EMM_REGISTERED_INITIATED); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_INITIATED); switch (evt->primitive) { case _EMMREG_ATTACH_INIT: @@ -96,14 +98,14 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) /* Move to the corresponding initial EMM state */ if (evt->u.attach.is_emergency) { - rc = emm_fsm_set_status(EMM_DEREGISTERED_LIMITED_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_LIMITED_SERVICE); } else { - rc = emm_fsm_set_status(EMM_DEREGISTERED_NORMAL_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NORMAL_SERVICE); } if (rc != RETURNerror) { /* Restart the attach procedure */ - rc = emm_proc_attach_restart(); + rc = emm_proc_attach_restart(user); } break; @@ -114,7 +116,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * timer T3410 expired). The network attach procedure shall be * restarted when timer T3411 expires. */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH); break; case _EMMREG_ATTACH_EXCEEDED: @@ -126,7 +128,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * SEARCH in order to perform a PLMN selection. */ /* TODO: ATTEMPTING-TO-ATTACH or PLMN-SEARCH ??? */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH); break; case _EMMREG_ATTACH_CNF: @@ -134,13 +136,13 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * EPS network attach accepted by the network; * enter state EMM-REGISTERED. */ - rc = emm_fsm_set_status(EMM_REGISTERED); + rc = emm_fsm_set_status(user, EMM_REGISTERED); if (rc != RETURNerror) { /* * Notify EMM that the MT is registered */ - rc = emm_proc_registration_notify(NET_REG_STATE_HN); + rc = emm_proc_registration_notify(user_api_id, emm_data, NET_REG_STATE_HN); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-FSM - " @@ -161,13 +163,13 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * EPS network attach rejected by the network; * enter state EMM-DEREGISTERED. */ - rc = emm_fsm_set_status(EMM_DEREGISTERED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED); if (rc != RETURNerror) { /* * Notify EMM that the MT's registration is denied */ - rc = emm_proc_registration_notify(NET_REG_STATE_DENIED); + rc = emm_proc_registration_notify(user_api_id, emm_data, NET_REG_STATE_DENIED); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-FSM - " @@ -181,11 +183,11 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) /* * The UE has to select a new PLMN to register to */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_PLMN_SEARCH); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_PLMN_SEARCH); if (rc != RETURNerror) { /* Process the network registration request */ - rc = emm_fsm_process(evt); + rc = emm_fsm_process(user, evt); } break; @@ -194,7 +196,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) /* * The UE failed to register to the network for normal EPS service */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_LIMITED_SERVICE); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_LIMITED_SERVICE); break; case _EMMREG_NO_IMSI: @@ -202,14 +204,14 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * The UE failed to register to the network for emergency * bearer services */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_NO_IMSI); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_NO_IMSI); break; case _EMMREG_DETACH_INIT: /* * Initiate detach procedure for EPS services */ - rc = emm_proc_detach(EMM_DETACH_TYPE_EPS, evt->u.detach.switch_off); + rc = emm_proc_detach(user, EMM_DETACH_TYPE_EPS, evt->u.detach.switch_off); break; case _EMMREG_DETACH_REQ: @@ -218,7 +220,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * message successfully delivered to the network); * enter state EMM-DEREGISTERED-INITIATED */ - rc = emm_fsm_set_status(EMM_DEREGISTERED_INITIATED); + rc = emm_fsm_set_status(user, EMM_DEREGISTERED_INITIATED); break; case _EMMREG_LOWERLAYER_SUCCESS: @@ -228,7 +230,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * any message transfered by EMM common procedures requested * by the network. */ - rc = emm_proc_lowerlayer_success(); + rc = emm_proc_lowerlayer_success(user->lowerlayer_data); break; case _EMMREG_LOWERLAYER_FAILURE: @@ -238,7 +240,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * any message transfered by EMM common procedures requested * by the network. */ - rc = emm_proc_lowerlayer_failure(FALSE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, FALSE); break; case _EMMREG_LOWERLAYER_RELEASE: @@ -247,7 +249,7 @@ int EmmRegisteredInitiated(const emm_reg_t *evt) * Accept, Attach Reject, or any message transfered by EMM common * procedures requested by the network, is received. */ - rc = emm_proc_lowerlayer_release(); + rc = emm_proc_lowerlayer_release(user->lowerlayer_data); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredLimitedService.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredLimitedService.c index 280252b8ed671eb1f827d04306dd40a16a08b0b9..b4ea68f689573330e45d844b076f180e2c92f0e8 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredLimitedService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredLimitedService.c @@ -74,11 +74,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredLimitedService(const emm_reg_t *evt) +int EmmRegisteredLimitedService(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_LIMITED_SERVICE); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_LIMITED_SERVICE); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredNoCellAvailable.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredNoCellAvailable.c index a22f3d76c6bbb4483f1254c74f8c7b112838d04c..0328ae81920f9eece5dddc709d377351222b09a9 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredNoCellAvailable.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredNoCellAvailable.c @@ -75,11 +75,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredNoCellAvailable(const emm_reg_t *evt) +int EmmRegisteredNoCellAvailable(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_NO_CELL_AVAILABLE); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_NO_CELL_AVAILABLE); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredNormalService.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredNormalService.c index bc25a1e4be693ac17211e1c9e9c38d66437084d6..8b1c8721f2d6f091645c0db14a19d22611e5b0f9 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredNormalService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredNormalService.c @@ -74,11 +74,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredNormalService(const emm_reg_t *evt) +int EmmRegisteredNormalService(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_NORMAL_SERVICE); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_NORMAL_SERVICE); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredPlmnSearch.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredPlmnSearch.c index 453e39558efc67646f330f6fc017f21ed971a7af..8ee92c4454cce5d18301cb6dbced9b0d8a7aab32 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredPlmnSearch.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredPlmnSearch.c @@ -74,46 +74,13 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredPlmnSearch(const emm_reg_t *evt) +int EmmRegisteredPlmnSearch(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_PLMN_SEARCH); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_PLMN_SEARCH); /* TODO */ LOG_FUNC_RETURN (RETURNok); } - -#if 0 -/**************************************************************************** - ** ** - ** Name: EmmRegisteredPlmnSearch_xxx() ** - ** ** - ** Description: Procedure executed when xxx ** - ** while the EMM-SAP is in EMM-REGISTERED.PLMN-SEARCH state. ** - ** ** - ** Inputs: evt: The received EMM-SAP event ** - ** Others: emm_fsm_status ** - ** ** - ** Outputs: None ** - ** Return: RETURNok, RETURNerror ** - ** Others: emm_fsm_status ** - ** ** - ***************************************************************************/ -int EmmRegisteredPlmnSearch_xxx(const emm_reg_t *evt) -{ - LOG_FUNC_IN; - - assert(emm_fsm_get_status() == EMM_REGISTERED_PLMN_SEARCH); - - /* TODO */ - - LOG_FUNC_RETURN (RETURNok); -} -#endif - -/****************************************************************************/ -/********************* L O C A L F U N C T I O N S *********************/ -/****************************************************************************/ - diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredUpdateNeeded.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredUpdateNeeded.c index 36f35fe351bdaa337e3152cd3d6baefca408bf4f..2a81b488dce0dd9ce5d71ff3609d392a0b2ae413 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredUpdateNeeded.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredUpdateNeeded.c @@ -80,11 +80,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmRegisteredUpdateNeeded(const emm_reg_t *evt) +int EmmRegisteredUpdateNeeded(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_REGISTERED_UPDATE_NEEDED); + assert(emm_fsm_get_status(user) == EMM_REGISTERED_UPDATE_NEEDED); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmServiceRequestInitiated.c b/openair3/NAS/UE/EMM/SAP/EmmServiceRequestInitiated.c index a72b2d6003e35431e9df061d79f1cf1362bf9250..b556efb7f44fa02ef98c75eeb0b13b8620b6ada7 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmServiceRequestInitiated.c +++ b/openair3/NAS/UE/EMM/SAP/EmmServiceRequestInitiated.c @@ -76,11 +76,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmServiceRequestInitiated(const emm_reg_t *evt) +int EmmServiceRequestInitiated(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_SERVICE_REQUEST_INITIATED); + assert(emm_fsm_get_status(user) == EMM_SERVICE_REQUEST_INITIATED); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c b/openair3/NAS/UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c index 69699cc117b5c86ef9b4df37ae08a2b931b3b18d..91bb660ee121f4b328a3d38a04d2590910e13244 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c +++ b/openair3/NAS/UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c @@ -76,11 +76,11 @@ Description Implements the EPS Mobility Management procedures executed ** Others: emm_fsm_status ** ** ** ***************************************************************************/ -int EmmTrackingAreaUpdatingInitiated(const emm_reg_t *evt) +int EmmTrackingAreaUpdatingInitiated(nas_user_t *user, const emm_reg_t *evt) { LOG_FUNC_IN; - assert(emm_fsm_get_status() == EMM_TRACKING_AREA_UPDATING_INITIATED); + assert(emm_fsm_get_status(user) == EMM_TRACKING_AREA_UPDATING_INITIATED); /* TODO */ diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index 7650f97ee88d0e43911a3adefe67594da0606e5a..d833b5bba08178921e45151d3e2114c096d1bb06 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -53,6 +53,8 @@ Description Defines the EMMAS Service Access Point that provides #include "emm_cause.h" #include "LowerLayer.h" +#include "emm_proc.h" + #include <string.h> // memset #include <stdlib.h> // malloc, free @@ -65,10 +67,6 @@ Description Defines the EMMAS Service Access Point that provides /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ -extern int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat); - -extern int emm_proc_status(unsigned int ueid, int emm_cause); - /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ @@ -99,19 +97,19 @@ static const char *_emm_as_primitive_str[] = { * Functions executed to process EMM procedures upon receiving * data from the network */ -static int _emm_as_recv(unsigned int ueid, const char *msg, int len, +static int _emm_as_recv(nas_user_t *user, const char *msg, int len, int *emm_cause); -static int _emm_as_establish_cnf(const emm_as_establish_t *msg, int *emm_cause); -static int _emm_as_establish_rej(void); -static int _emm_as_release_ind(const emm_as_release_t *msg); +static int _emm_as_establish_cnf(nas_user_t *user, const emm_as_establish_t *msg, int *emm_cause); +static int _emm_as_establish_rej(nas_user_t *user); +static int _emm_as_release_ind(nas_user_t *user, const emm_as_release_t *msg); static int _emm_as_page_ind(const emm_as_page_t *msg); -static int _emm_as_cell_info_res(const emm_as_cell_info_t *msg); +static int _emm_as_cell_info_res(nas_user_t *user, const emm_as_cell_info_t *msg); static int _emm_as_cell_info_ind(const emm_as_cell_info_t *msg); -static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause); +static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm_cause); /* * Functions executed to send data to the network when requested @@ -133,18 +131,18 @@ static int _emm_as_encrypt( int length, emm_security_context_t *emm_security_context); -static int _emm_as_send(const emm_as_t *msg); +static int _emm_as_send(const nas_user_t *user, const emm_as_t *msg); -static int _emm_as_security_res(const emm_as_security_t *, +static int _emm_as_security_res(const emm_data_t *emm_data, const emm_as_security_t *, ul_info_transfer_req_t *); -static int _emm_as_establish_req(const emm_as_establish_t *, +static int _emm_as_establish_req(const emm_data_t *emm_data, const emm_as_establish_t *, nas_establish_req_t *); static int _emm_as_cell_info_req(const emm_as_cell_info_t *, cell_info_req_t *); -static int _emm_as_data_req(const emm_as_data_t *, ul_info_transfer_req_t *); -static int _emm_as_status_ind(const emm_as_status_t *, ul_info_transfer_req_t *); +static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg, ul_info_transfer_req_t *); +static int _emm_as_status_ind(const emm_data_t *emm_data, const emm_as_status_t *, ul_info_transfer_req_t *); static int _emm_as_release_req(const emm_as_release_t *, nas_release_req_t *); /****************************************************************************/ @@ -165,7 +163,7 @@ static int _emm_as_release_req(const emm_as_release_t *, nas_release_req_t *); ** Others: NONE ** ** ** ***************************************************************************/ -void emm_as_initialize(void) +void emm_as_initialize(nas_user_t *user) { LOG_FUNC_IN; @@ -188,7 +186,7 @@ void emm_as_initialize(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_as_send(const emm_as_t *msg) +int emm_as_send(nas_user_t *user, const emm_as_t *msg) { LOG_FUNC_IN; @@ -196,28 +194,25 @@ int emm_as_send(const emm_as_t *msg) int emm_cause = EMM_CAUSE_SUCCESS; emm_as_primitive_t primitive = msg->primitive; - uint32_t ueid = 0; - LOG_TRACE(INFO, "EMMAS-SAP - Received primitive %s (%d)", _emm_as_primitive_str[primitive - _EMMAS_START - 1], primitive); switch (primitive) { case _EMMAS_DATA_IND: - rc = _emm_as_data_ind(&msg->u.data, &emm_cause); - ueid = msg->u.data.ueid; + rc = _emm_as_data_ind(user, &msg->u.data, &emm_cause); break; case _EMMAS_ESTABLISH_CNF: - rc = _emm_as_establish_cnf(&msg->u.establish, &emm_cause); + rc = _emm_as_establish_cnf(user, &msg->u.establish, &emm_cause); break; case _EMMAS_ESTABLISH_REJ: - rc = _emm_as_establish_rej(); + rc = _emm_as_establish_rej(user); break; case _EMMAS_RELEASE_IND: - rc = _emm_as_release_ind(&msg->u.release); + rc = _emm_as_release_ind(user, &msg->u.release); break; case _EMMAS_PAGE_IND: @@ -225,7 +220,7 @@ int emm_as_send(const emm_as_t *msg) break; case _EMMAS_CELL_INFO_RES: - rc = _emm_as_cell_info_res(&msg->u.cell_info); + rc = _emm_as_cell_info_res(user, &msg->u.cell_info); break; case _EMMAS_CELL_INFO_IND: @@ -234,7 +229,7 @@ int emm_as_send(const emm_as_t *msg) default: /* Other primitives are forwarded to the Access Stratum */ - rc = _emm_as_send(msg); + rc = _emm_as_send(user, msg); if (rc != RETURNok) { LOG_TRACE(ERROR, "EMMAS-SAP - " @@ -266,7 +261,7 @@ int emm_as_send(const emm_as_t *msg) LOG_TRACE(WARNING, "EMMAS-SAP - Received EMM message is not valid " "(cause=%d)", emm_cause); /* Return an EMM status message */ - rc = emm_proc_status(ueid, emm_cause); + rc = emm_proc_status(user, emm_cause); } if (rc != RETURNok) { @@ -306,7 +301,7 @@ int emm_as_send(const emm_as_t *msg) ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_recv(unsigned int ueid, const char *msg, int len, +static int _emm_as_recv(nas_user_t *user, const char *msg, int len, int *emm_cause) { LOG_FUNC_IN; @@ -321,7 +316,7 @@ static int _emm_as_recv(unsigned int ueid, const char *msg, int len, emm_security_context_t *security = NULL; /* Current EPS NAS security context */ - security = _emm_data.security; + security = user->emm_data->security; /* Decode the received message */ decoder_rc = nas_message_decode(msg, &nas_msg, len, security); @@ -338,34 +333,34 @@ static int _emm_as_recv(unsigned int ueid, const char *msg, int len, switch (emm_msg->header.message_type) { case EMM_STATUS: - rc = emm_recv_status(ueid, &emm_msg->emm_status, emm_cause); + rc = emm_recv_status(user->ueid, &emm_msg->emm_status, emm_cause); break; case IDENTITY_REQUEST: - rc = emm_recv_identity_request(&emm_msg->identity_request, + rc = emm_recv_identity_request(user, &emm_msg->identity_request, emm_cause); break; case AUTHENTICATION_REQUEST: - rc = emm_recv_authentication_request( + rc = emm_recv_authentication_request(user, &emm_msg->authentication_request, emm_cause); break; case AUTHENTICATION_REJECT: - rc = emm_recv_authentication_reject( + rc = emm_recv_authentication_reject(user, &emm_msg->authentication_reject, emm_cause); break; case SECURITY_MODE_COMMAND: - rc = emm_recv_security_mode_command( + rc = emm_recv_security_mode_command(user, &emm_msg->security_mode_command, emm_cause); break; case DETACH_ACCEPT: - rc = emm_recv_detach_accept(&emm_msg->detach_accept, emm_cause); + rc = emm_recv_detach_accept(user, &emm_msg->detach_accept, emm_cause); break; @@ -406,7 +401,7 @@ static int _emm_as_recv(unsigned int ueid, const char *msg, int len, ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause) +static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm_cause) { LOG_FUNC_IN; @@ -428,7 +423,7 @@ static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause) memset(&header, 0, sizeof(header)); /* Decrypt the received security protected message */ - security = _emm_data.security; + security = user->emm_data->security; int bytes = nas_message_decrypt((char *)(msg->NASmsg.value), plain_msg, &header, @@ -443,23 +438,23 @@ static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause) } else if (header.protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) { /* Process EMM data */ - rc = _emm_as_recv(msg->ueid, plain_msg, bytes, emm_cause); + rc = _emm_as_recv(user, plain_msg, bytes, emm_cause); } else if (header.protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) { const OctetString data = {bytes, (uint8_t *)plain_msg}; /* Foward ESM data to EPS session management */ - rc = lowerlayer_data_ind(msg->ueid, &data); + rc = lowerlayer_data_ind(user, &data); } free(plain_msg); } } else { /* Process successfull lower layer transfer indication */ - rc = lowerlayer_success(msg->ueid); + rc = lowerlayer_success(user); } } else { /* Process lower layer transmission failure of NAS message */ - rc = lowerlayer_failure(msg->ueid); + rc = lowerlayer_failure(user); } LOG_FUNC_RETURN (rc); @@ -482,7 +477,7 @@ static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause) ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_establish_cnf(const emm_as_establish_t *msg, +static int _emm_as_establish_cnf(nas_user_t *user, const emm_as_establish_t *msg, int *emm_cause) { LOG_FUNC_IN; @@ -494,11 +489,11 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg, if (msg->NASmsg.length > 0) { /* The NAS signalling connection is established */ - (void) lowerlayer_establish(); + (void) lowerlayer_establish(user); } else { /* The initial NAS message has been successfully delivered to * lower layers */ - rc = lowerlayer_success(0); + rc = lowerlayer_success(user); LOG_FUNC_RETURN (rc); } @@ -509,7 +504,7 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg, decoder_rc = nas_message_decode((char *)(msg->NASmsg.value), &nas_msg, msg->NASmsg.length, - _emm_data.security); + user->emm_data->security); if (decoder_rc < 0) { LOG_TRACE(WARNING, "EMMAS-SAP - Failed to decode initial NAS message" @@ -523,11 +518,11 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg, switch (emm_msg->header.message_type) { case ATTACH_ACCEPT: - rc = emm_recv_attach_accept(&emm_msg->attach_accept, emm_cause); + rc = emm_recv_attach_accept(user, &emm_msg->attach_accept, emm_cause); break; case ATTACH_REJECT: - rc = emm_recv_attach_reject(&emm_msg->attach_reject, emm_cause); + rc = emm_recv_attach_reject(user, &emm_msg->attach_reject, emm_cause); break; case DETACH_ACCEPT: @@ -563,7 +558,7 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg, ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_establish_rej(void) +static int _emm_as_establish_rej(nas_user_t *user) { LOG_FUNC_IN; @@ -573,7 +568,7 @@ static int _emm_as_establish_rej(void) "failure"); /* Process lower layer transmission failure of initial NAS message */ - rc = lowerlayer_failure(0); + rc = lowerlayer_failure(user); LOG_FUNC_RETURN (rc); } @@ -595,7 +590,7 @@ static int _emm_as_establish_rej(void) ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_release_ind(const emm_as_release_t *msg) +static int _emm_as_release_ind(nas_user_t *user, const emm_as_release_t *msg) { LOG_FUNC_IN; @@ -605,7 +600,7 @@ static int _emm_as_release_ind(const emm_as_release_t *msg) "(cause=%d)", msg->cause); /* Process NAS signalling connection release indication */ - rc = lowerlayer_release(msg->cause); + rc = lowerlayer_release(user, msg->cause); LOG_FUNC_RETURN (rc); } @@ -663,7 +658,7 @@ static int _emm_as_page_ind(const emm_as_page_t *msg) ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_cell_info_res(const emm_as_cell_info_t *msg) +static int _emm_as_cell_info_res(nas_user_t *user, const emm_as_cell_info_t *msg) { LOG_FUNC_IN; @@ -685,7 +680,7 @@ static int _emm_as_cell_info_res(const emm_as_cell_info_t *msg) } /* Notify EMM that a cell has been found */ - rc = emm_proc_plmn_selection_end(msg->found, msg->tac, msg->cellID, AcT); + rc = emm_proc_plmn_selection_end(user, msg->found, msg->tac, msg->cellID, AcT); LOG_FUNC_RETURN (rc); } @@ -928,7 +923,7 @@ _emm_as_encrypt( ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_send(const emm_as_t *msg) +static int _emm_as_send(const nas_user_t *user, const emm_as_t *msg) { LOG_FUNC_IN; @@ -937,13 +932,13 @@ static int _emm_as_send(const emm_as_t *msg) switch (msg->primitive) { case _EMMAS_DATA_REQ: - as_msg.msgID = _emm_as_data_req( + as_msg.msgID = _emm_as_data_req(user->emm_data, &msg->u.data, &as_msg.msg.ul_info_transfer_req); break; case _EMMAS_STATUS_IND: - as_msg.msgID = _emm_as_status_ind( + as_msg.msgID = _emm_as_status_ind(user->emm_data, &msg->u.status, &as_msg.msg.ul_info_transfer_req); break; @@ -956,13 +951,13 @@ static int _emm_as_send(const emm_as_t *msg) case _EMMAS_SECURITY_RES: - as_msg.msgID = _emm_as_security_res( + as_msg.msgID = _emm_as_security_res(user->emm_data, &msg->u.security, &as_msg.msg.ul_info_transfer_req); break; case _EMMAS_ESTABLISH_REQ: - as_msg.msgID = _emm_as_establish_req( + as_msg.msgID = _emm_as_establish_req(user->emm_data, &msg->u.establish, &as_msg.msg.nas_establish_req); break; @@ -996,7 +991,8 @@ static int _emm_as_send(const emm_as_t *msg) case AS_CELL_INFO_REQ: { nas_itti_cell_info_req( as_msg.msg.cell_info_req.plmnID, - as_msg.msg.cell_info_req.rat); + as_msg.msg.cell_info_req.rat, + user->ueid); LOG_FUNC_RETURN (RETURNok); } break; @@ -1008,7 +1004,8 @@ static int _emm_as_send(const emm_as_t *msg) as_msg.msg.nas_establish_req.s_tmsi, as_msg.msg.nas_establish_req.plmnID, as_msg.msg.nas_establish_req.initialNasMsg.data, - as_msg.msg.nas_establish_req.initialNasMsg.length); + as_msg.msg.nas_establish_req.initialNasMsg.length, + user->ueid); LOG_FUNC_RETURN (RETURNok); } break; @@ -1017,7 +1014,8 @@ static int _emm_as_send(const emm_as_t *msg) nas_itti_ul_data_req( as_msg.msg.ul_info_transfer_req.UEid, as_msg.msg.ul_info_transfer_req.nasMsg.data, - as_msg.msg.ul_info_transfer_req.nasMsg.length); + as_msg.msg.ul_info_transfer_req.nasMsg.length, + user->ueid); LOG_FUNC_RETURN (RETURNok); } break; @@ -1026,7 +1024,8 @@ static int _emm_as_send(const emm_as_t *msg) nas_itti_rab_establish_rsp( as_msg.msg.rab_establish_rsp.s_tmsi, as_msg.msg.rab_establish_rsp.rabID, - as_msg.msg.rab_establish_rsp.errCode); + as_msg.msg.rab_establish_rsp.errCode, + user->ueid); LOG_FUNC_RETURN (RETURNok); } break; @@ -1065,7 +1064,7 @@ static int _emm_as_send(const emm_as_t *msg) ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_data_req(const emm_as_data_t *msg, +static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg, ul_info_transfer_req_t *as_msg) { LOG_FUNC_IN; @@ -1112,7 +1111,7 @@ static int _emm_as_data_req(const emm_as_data_t *msg, int bytes; emm_security_context_t *emm_security_context = NULL; - emm_security_context = _emm_data.security; + emm_security_context = emm_data->security; if (emm_security_context) { @@ -1161,7 +1160,7 @@ static int _emm_as_data_req(const emm_as_data_t *msg, ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_status_ind(const emm_as_status_t *msg, +static int _emm_as_status_ind(const emm_data_t *emm_data, const emm_as_status_t *msg, ul_info_transfer_req_t *as_msg) { LOG_FUNC_IN; @@ -1193,7 +1192,7 @@ static int _emm_as_status_ind(const emm_as_status_t *msg, if (size > 0) { emm_security_context_t *emm_security_context = NULL; - emm_security_context = _emm_data.security; + emm_security_context = emm_data->security; if (emm_security_context) { @@ -1275,7 +1274,7 @@ static int _emm_as_release_req(const emm_as_release_t *msg, ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_security_res(const emm_as_security_t *msg, +static int _emm_as_security_res(const emm_data_t *emm_data, const emm_as_security_t *msg, ul_info_transfer_req_t *as_msg) { LOG_FUNC_IN; @@ -1340,7 +1339,7 @@ static int _emm_as_security_res(const emm_as_security_t *msg, int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size, - _emm_data.security); + emm_data->security); if (bytes > 0) { LOG_FUNC_RETURN (AS_UL_INFO_TRANSFER_REQ); @@ -1369,7 +1368,7 @@ static int _emm_as_security_res(const emm_as_security_t *msg, ** Others: None ** ** ** ***************************************************************************/ -static int _emm_as_establish_req(const emm_as_establish_t *msg, +static int _emm_as_establish_req(const emm_data_t *emm_data, const emm_as_establish_t *msg, nas_establish_req_t *as_msg) { LOG_FUNC_IN; @@ -1433,7 +1432,7 @@ static int _emm_as_establish_req(const emm_as_establish_t *msg, &as_msg->initialNasMsg, &nas_msg, size, - _emm_data.security); + emm_data->security); if (bytes > 0) { LOG_FUNC_RETURN (AS_NAS_ESTABLISH_REQ); diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.h b/openair3/NAS/UE/EMM/SAP/emm_as.h index 04a14cf3cb26f84cd681315bd76e4d3370e9fcc7..726a363d75c859d4ae8381a44e00c29b951f23e3 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.h +++ b/openair3/NAS/UE/EMM/SAP/emm_as.h @@ -41,6 +41,7 @@ Description Defines the EMMAS Service Access Point that provides #define __EMM_AS_H__ #include "emm_asDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -58,8 +59,8 @@ Description Defines the EMMAS Service Access Point that provides /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void emm_as_initialize(void); +void emm_as_initialize(nas_user_t *user); -int emm_as_send(const emm_as_t *msg); +int emm_as_send(nas_user_t *user, const emm_as_t *msg); #endif /* __EMM_AS_H__*/ diff --git a/openair3/NAS/UE/EMM/SAP/emm_esm.c b/openair3/NAS/UE/EMM/SAP/emm_esm.c index a12d71d79beca3d6458aaadf49998dcbe213de83..798e682b112c09f7d54ccebcb4b7dc6fec0492a9 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_esm.c +++ b/openair3/NAS/UE/EMM/SAP/emm_esm.c @@ -108,7 +108,7 @@ void emm_esm_initialize(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_esm_send(const emm_esm_t *msg) +int emm_esm_send(nas_user_t *user, const emm_esm_t *msg) { LOG_FUNC_IN; @@ -123,7 +123,7 @@ int emm_esm_send(const emm_esm_t *msg) case _EMMESM_ESTABLISH_REQ: /* ESM requests EMM to initiate an attach procedure before * requesting subsequent connectivity to additional PDNs */ - rc = emm_proc_attach_restart(); + rc = emm_proc_attach_restart(user); break; case _EMMESM_ESTABLISH_CNF: @@ -134,11 +134,11 @@ int emm_esm_send(const emm_esm_t *msg) if (msg->u.establish.is_emergency) { /* Consider the UE attached for emergency bearer services * only */ - rc = emm_proc_attach_set_emergency(); + rc = emm_proc_attach_set_emergency(user->emm_data); } } else { /* Consider the UE locally detached from the network */ - rc = emm_proc_attach_set_detach(); + rc = emm_proc_attach_set_detach(user); } break; @@ -149,7 +149,7 @@ int emm_esm_send(const emm_esm_t *msg) case _EMMESM_UNITDATA_REQ: /* ESM requests EMM to transfer ESM data unit to lower layer */ - rc = lowerlayer_data_req(msg->ueid, &msg->u.data.msg); + rc = lowerlayer_data_req(user, &msg->u.data.msg); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/emm_esm.h b/openair3/NAS/UE/EMM/SAP/emm_esm.h index 7a763d4759a3788c5f5808b130e89012fdd6ca70..11aa42213f8f7681e9399104db26980741339149 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_esm.h +++ b/openair3/NAS/UE/EMM/SAP/emm_esm.h @@ -42,6 +42,7 @@ Description Defines the EMMESM Service Access Point that provides #define __EMM_ESM_H__ #include "emm_esmDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -61,6 +62,6 @@ Description Defines the EMMESM Service Access Point that provides void emm_esm_initialize(void); -int emm_esm_send(const emm_esm_t *msg); +int emm_esm_send(nas_user_t *user, const emm_esm_t *msg); #endif /* __EMM_ESM_H__*/ diff --git a/openair3/NAS/UE/EMM/SAP/emm_fsm.c b/openair3/NAS/UE/EMM/SAP/emm_fsm.c index a76b101119b11e0551235fa99f115f1420a87fcb..be1517a7ccd21d4c051394ef0be29adac95658fa 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_fsm.c +++ b/openair3/NAS/UE/EMM/SAP/emm_fsm.c @@ -43,6 +43,7 @@ Description Defines the EPS Mobility Management procedures executed at #include "nas_log.h" #include "emmData.h" +#include "user_defs.h" @@ -127,30 +128,30 @@ static const char *_emm_fsm_status_str[EMM_STATE_MAX] = { */ /* Type of the EPS Mobility Management state machine handler */ -typedef int(*emm_fsm_handler_t)(const emm_reg_t *); - -int EmmNull(const emm_reg_t *); -int EmmDeregistered(const emm_reg_t *); -int EmmRegistered(const emm_reg_t *); -int EmmDeregisteredInitiated(const emm_reg_t *); -int EmmDeregisteredNormalService(const emm_reg_t *); -int EmmDeregisteredLimitedService(const emm_reg_t *); -int EmmDeregisteredAttemptingToAttach(const emm_reg_t *); -int EmmDeregisteredPlmnSearch(const emm_reg_t *); -int EmmDeregisteredNoImsi(const emm_reg_t *); -int EmmDeregisteredAttachNeeded(const emm_reg_t *); -int EmmDeregisteredNoCellAvailable(const emm_reg_t *); -int EmmRegisteredInitiated(const emm_reg_t *); -int EmmRegisteredNormalService(const emm_reg_t *); -int EmmRegisteredAttemptingToUpdate(const emm_reg_t *); -int EmmRegisteredLimitedService(const emm_reg_t *); -int EmmRegisteredPlmnSearch(const emm_reg_t *); -int EmmRegisteredUpdateNeeded(const emm_reg_t *); -int EmmRegisteredNoCellAvailable(const emm_reg_t *); -int EmmRegisteredAttemptingToUpdate(const emm_reg_t *); -int EmmRegisteredImsiDetachInitiated(const emm_reg_t *); -int EmmTrackingAreaUpdatingInitiated(const emm_reg_t *); -int EmmServiceRequestInitiated(const emm_reg_t *); +typedef int(*emm_fsm_handler_t)(nas_user_t *user, const emm_reg_t *); + +int EmmNull(nas_user_t *user, const emm_reg_t *); +int EmmDeregistered(nas_user_t *user, const emm_reg_t *); +int EmmRegistered(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredInitiated(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredNormalService(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredLimitedService(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredAttemptingToAttach(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredPlmnSearch(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredNoImsi(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredAttachNeeded(nas_user_t *user, const emm_reg_t *); +int EmmDeregisteredNoCellAvailable(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredInitiated(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredNormalService(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredAttemptingToUpdate(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredLimitedService(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredPlmnSearch(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredUpdateNeeded(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredNoCellAvailable(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredAttemptingToUpdate(nas_user_t *user, const emm_reg_t *); +int EmmRegisteredImsiDetachInitiated(nas_user_t *user, const emm_reg_t *); +int EmmTrackingAreaUpdatingInitiated(nas_user_t *user, const emm_reg_t *); +int EmmServiceRequestInitiated(nas_user_t *user, const emm_reg_t *); /* EMM state machine handlers */ @@ -180,14 +181,6 @@ static const emm_fsm_handler_t _emm_fsm_handlers[EMM_STATE_MAX] = { EmmServiceRequestInitiated, }; -/* - * ----------------------------------------------------------------------------- - * Current EPS Mobility Management status - * ----------------------------------------------------------------------------- - */ - -emm_fsm_state_t _emm_fsm_status[EMM_FSM_NB_UE_MAX]; - /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ @@ -206,14 +199,12 @@ emm_fsm_state_t _emm_fsm_status[EMM_FSM_NB_UE_MAX]; ** Others: _emm_fsm_status ** ** ** ***************************************************************************/ -void emm_fsm_initialize(void) +emm_fsm_state_t emm_fsm_initialize() { - //int ueid; LOG_FUNC_IN; - _emm_fsm_status[0] = EMM_NULL; - LOG_FUNC_OUT; + return EMM_NULL; } /**************************************************************************** @@ -231,22 +222,18 @@ void emm_fsm_initialize(void) ** Others: _emm_fsm_status ** ** ** ***************************************************************************/ -int emm_fsm_set_status( +int emm_fsm_set_status(nas_user_t *user, emm_fsm_state_t status) { LOG_FUNC_IN; - unsigned int ueid = 0; - - - - if ( (status < EMM_STATE_MAX) && (ueid < EMM_FSM_NB_UE_MAX) ) { + if ( status < EMM_STATE_MAX ) { LOG_TRACE(INFO, "EMM-FSM - Status changed: %s ===> %s", - _emm_fsm_status_str[_emm_fsm_status[ueid]], + _emm_fsm_status_str[user->emm_fsm_status], _emm_fsm_status_str[status]); - if (status != _emm_fsm_status[ueid]) { - _emm_fsm_status[ueid] = status; + if (status != user->emm_fsm_status) { + user->emm_fsm_status = status; } LOG_FUNC_RETURN (RETURNok); @@ -270,9 +257,9 @@ int emm_fsm_set_status( ** Others: None ** ** ** ***************************************************************************/ -emm_fsm_state_t emm_fsm_get_status(void) +emm_fsm_state_t emm_fsm_get_status(nas_user_t *user) { - return (_emm_fsm_status[0]); + return user->emm_fsm_status; } /**************************************************************************** @@ -289,7 +276,7 @@ emm_fsm_state_t emm_fsm_get_status(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_fsm_process(const emm_reg_t *evt) +int emm_fsm_process(nas_user_t *user, const emm_reg_t *evt) { int rc; emm_fsm_state_t status; @@ -299,7 +286,7 @@ int emm_fsm_process(const emm_reg_t *evt) primitive = evt->primitive; - status = _emm_fsm_status[0]; + status = user->emm_fsm_status; LOG_TRACE(INFO, "EMM-FSM - Received event %s (%d) in state %s", _emm_fsm_event_str[primitive - _EMMREG_START - 1], primitive, @@ -307,7 +294,7 @@ int emm_fsm_process(const emm_reg_t *evt) /* Execute the EMM state machine */ - rc = (_emm_fsm_handlers[status])(evt); + rc = (_emm_fsm_handlers[status])(user, evt); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/EMM/SAP/emm_fsm.h b/openair3/NAS/UE/EMM/SAP/emm_fsm.h index ea7d4ed62228cf6875aad3e31ede55437a1c64b2..aba1ef327ca2e8f5f010ece712a501c2600dc625 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_fsm.h +++ b/openair3/NAS/UE/EMM/SAP/emm_fsm.h @@ -41,48 +41,13 @@ Description Defines the EPS Mobility Management procedures executed at #define __EMM_FSM_H__ #include "emm_regDef.h" +#include "emm_fsm_defs.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ -/****************************************************************************/ -/************************ G L O B A L T Y P E S ************************/ -/****************************************************************************/ - -/* - * States of the EPS Mobility Management sublayer - * ---------------------------------------------- - * The EMM protocol of the UE and the network is described by means of two - * different state machines. - */ -typedef enum { - EMM_INVALID, - EMM_NULL, - EMM_DEREGISTERED, - EMM_REGISTERED, - EMM_DEREGISTERED_INITIATED, - EMM_DEREGISTERED_NORMAL_SERVICE, - EMM_DEREGISTERED_LIMITED_SERVICE, - EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH, - EMM_DEREGISTERED_PLMN_SEARCH, - EMM_DEREGISTERED_NO_IMSI, - EMM_DEREGISTERED_ATTACH_NEEDED, - EMM_DEREGISTERED_NO_CELL_AVAILABLE, - EMM_REGISTERED_INITIATED, - EMM_REGISTERED_NORMAL_SERVICE, - EMM_REGISTERED_ATTEMPTING_TO_UPDATE, - EMM_REGISTERED_LIMITED_SERVICE, - EMM_REGISTERED_PLMN_SEARCH, - EMM_REGISTERED_UPDATE_NEEDED, - EMM_REGISTERED_NO_CELL_AVAILABLE, - EMM_REGISTERED_ATTEMPTING_TO_UPDATE_MM, - EMM_REGISTERED_IMSI_DETACH_INITIATED, - EMM_TRACKING_AREA_UPDATING_INITIATED, - EMM_SERVICE_REQUEST_INITIATED, - EMM_STATE_MAX -} emm_fsm_state_t; - /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ @@ -91,12 +56,12 @@ typedef enum { /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void emm_fsm_initialize(void); +emm_fsm_state_t emm_fsm_initialize(void); -int emm_fsm_set_status(emm_fsm_state_t status); -emm_fsm_state_t emm_fsm_get_status(void); +int emm_fsm_set_status(nas_user_t *user, emm_fsm_state_t status); +emm_fsm_state_t emm_fsm_get_status(nas_user_t *user); -int emm_fsm_process(const emm_reg_t *evt); +int emm_fsm_process(nas_user_t *user, const emm_reg_t *evt); #endif /* __EMM_FSM_H__*/ diff --git a/openair3/NAS/UE/EMM/SAP/emm_recv.c b/openair3/NAS/UE/EMM/SAP/emm_recv.c index 0ad41b09d878862b677cc35da535f103baf1cadf..5b7c6d7dda34fe0c057da04071522ceeefffa69f 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_recv.c +++ b/openair3/NAS/UE/EMM/SAP/emm_recv.c @@ -125,7 +125,7 @@ int emm_recv_status(unsigned int ueid, emm_status_msg *msg, int *emm_cause) ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_attach_accept(attach_accept_msg *msg, int *emm_cause) +int emm_recv_attach_accept(nas_user_t *user, attach_accept_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -224,7 +224,7 @@ int emm_recv_attach_accept(attach_accept_msg *msg, int *emm_cause) } /* Execute attach procedure accepted by the network */ - rc = emm_proc_attach_accept(T3412, T3402, T3423, n_tais, tai, pguti, + rc = emm_proc_attach_accept(user, T3412, T3402, T3423, n_tais, tai, pguti, n_eplmns, &eplmn, &msg->esmmessagecontainer.esmmessagecontainercontents); @@ -245,7 +245,7 @@ int emm_recv_attach_accept(attach_accept_msg *msg, int *emm_cause) ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_attach_reject(attach_reject_msg *msg, int *emm_cause) +int emm_recv_attach_reject(nas_user_t *user, attach_reject_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -275,11 +275,11 @@ int emm_recv_attach_reject(attach_reject_msg *msg, int *emm_cause) */ if (msg->presencemask & ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT) { /* Execute attach procedure rejected by the network */ - rc = emm_proc_attach_reject(msg->emmcause, + rc = emm_proc_attach_reject(user, msg->emmcause, &msg->esmmessagecontainer.esmmessagecontainercontents); } else { /* Execute attach procedure rejected by the network */ - rc = emm_proc_attach_reject(msg->emmcause, NULL); + rc = emm_proc_attach_reject(user, msg->emmcause, NULL); } LOG_FUNC_RETURN (rc); @@ -299,7 +299,7 @@ int emm_recv_attach_reject(attach_reject_msg *msg, int *emm_cause) ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_detach_accept(detach_accept_msg *msg, int *emm_cause) +int emm_recv_detach_accept(nas_user_t *user, detach_accept_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -311,7 +311,7 @@ int emm_recv_detach_accept(detach_accept_msg *msg, int *emm_cause) * Message processing */ /* Execute the UE initiated detach procedure completion by the UE */ - rc = emm_proc_detach_accept(); + rc = emm_proc_detach_accept(user); LOG_FUNC_RETURN (rc); } @@ -330,7 +330,7 @@ int emm_recv_detach_accept(detach_accept_msg *msg, int *emm_cause) ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_identity_request(identity_request_msg *msg, int *emm_cause) +int emm_recv_identity_request(nas_user_t *user, identity_request_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -358,7 +358,7 @@ int emm_recv_identity_request(identity_request_msg *msg, int *emm_cause) } /* Execute the identification procedure initiated by the network */ - rc = emm_proc_identification_request(type); + rc = emm_proc_identification_request(user, type); LOG_FUNC_RETURN (rc); } @@ -377,7 +377,7 @@ int emm_recv_identity_request(identity_request_msg *msg, int *emm_cause) ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_authentication_request(authentication_request_msg *msg, +int emm_recv_authentication_request(nas_user_t *user, authentication_request_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -404,7 +404,7 @@ int emm_recv_authentication_request(authentication_request_msg *msg, * Message processing */ /* Execute the authentication procedure initiated by the network */ - rc = emm_proc_authentication_request( + rc = emm_proc_authentication_request(user, msg->naskeysetidentifierasme.tsc != NAS_KEY_SET_IDENTIFIER_MAPPED, msg->naskeysetidentifierasme.naskeysetidentifier, &msg->authenticationparameterrand.rand, @@ -427,7 +427,7 @@ int emm_recv_authentication_request(authentication_request_msg *msg, ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_authentication_reject(authentication_reject_msg *msg, +int emm_recv_authentication_reject(nas_user_t *user, authentication_reject_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -440,7 +440,7 @@ int emm_recv_authentication_reject(authentication_reject_msg *msg, * Message processing */ /* Execute the authentication procedure not accepted by the network */ - rc = emm_proc_authentication_reject(); + rc = emm_proc_authentication_reject(user); LOG_FUNC_RETURN (rc); } @@ -459,7 +459,7 @@ int emm_recv_authentication_reject(authentication_reject_msg *msg, ** Others: None ** ** ** ***************************************************************************/ -int emm_recv_security_mode_command(security_mode_command_msg *msg, +int emm_recv_security_mode_command(nas_user_t *user, security_mode_command_msg *msg, int *emm_cause) { LOG_FUNC_IN; @@ -473,7 +473,7 @@ int emm_recv_security_mode_command(security_mode_command_msg *msg, */ /* Execute the security mode control procedure initiated by the network */ LOG_TRACE(INFO,"Execute the security mode control procedure initiated by the network: imeisvrequest %d\n",msg->imeisvrequest); - rc = emm_proc_security_mode_command( + rc = emm_proc_security_mode_command(user, msg->naskeysetidentifier.tsc != NAS_KEY_SET_IDENTIFIER_MAPPED, msg->naskeysetidentifier.naskeysetidentifier, msg->selectednassecurityalgorithms.typeofcipheringalgorithm, diff --git a/openair3/NAS/UE/EMM/SAP/emm_recv.h b/openair3/NAS/UE/EMM/SAP/emm_recv.h index cec52a8c1f4025535403eff57719e0d5a096c834..ead59e3851bcfb44cf5224ac8942f218da24fc82 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_recv.h +++ b/openair3/NAS/UE/EMM/SAP/emm_recv.h @@ -59,7 +59,7 @@ Description Defines functions executed at the EMMAS Service Access #include "EmmInformation.h" #include "DownlinkNasTransport.h" #include "CsServiceNotification.h" - +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ @@ -88,17 +88,17 @@ int emm_recv_status(unsigned int ueid, emm_status_msg *msg, int *emm_cause); * Functions executed by the UE upon receiving EMM message from the network * -------------------------------------------------------------------------- */ -int emm_recv_attach_accept(attach_accept_msg *msg, int *emm_cause); -int emm_recv_attach_reject(attach_reject_msg *msg, int *emm_cause); +int emm_recv_attach_accept(nas_user_t *user, attach_accept_msg *msg, int *emm_cause); +int emm_recv_attach_reject(nas_user_t *user, attach_reject_msg *msg, int *emm_cause); -int emm_recv_detach_accept(detach_accept_msg *msg, int *emm_cause); +int emm_recv_detach_accept(nas_user_t *user, detach_accept_msg *msg, int *emm_cause); -int emm_recv_identity_request(identity_request_msg *msg, int *emm_cause); -int emm_recv_authentication_request(authentication_request_msg *msg, +int emm_recv_identity_request(nas_user_t *user, identity_request_msg *msg, int *emm_cause); +int emm_recv_authentication_request(nas_user_t *user, authentication_request_msg *msg, int *emm_cause); -int emm_recv_authentication_reject(authentication_reject_msg *msg, +int emm_recv_authentication_reject(nas_user_t *user, authentication_reject_msg *msg, int *emm_cause); -int emm_recv_security_mode_command(security_mode_command_msg *msg, +int emm_recv_security_mode_command(nas_user_t *user, security_mode_command_msg *msg, int *emm_cause); #endif /* __EMM_RECV_H__*/ diff --git a/openair3/NAS/UE/EMM/SAP/emm_reg.c b/openair3/NAS/UE/EMM/SAP/emm_reg.c index 065b91bd3ba0eda105e9ab0c08be1e827a77a9c2..6cda066b584d89098421139fcf9f6f60d4dd7256 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_reg.c +++ b/openair3/NAS/UE/EMM/SAP/emm_reg.c @@ -73,12 +73,12 @@ Description Defines the EMMREG Service Access Point that provides ** Others: NONE ** ** ** ***************************************************************************/ -void emm_reg_initialize(void) +void emm_reg_initialize(nas_user_t *user) { LOG_FUNC_IN; /* Initialize the EMM state machine */ - emm_fsm_initialize(); + user->emm_fsm_status = emm_fsm_initialize(); LOG_FUNC_OUT; } @@ -97,7 +97,7 @@ void emm_reg_initialize(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_reg_send(const emm_reg_t *msg) +int emm_reg_send(nas_user_t *user, const emm_reg_t *msg) { LOG_FUNC_IN; @@ -111,7 +111,7 @@ int emm_reg_send(const emm_reg_t *msg) (void)primitive; /* Execute the EMM procedure */ - rc = emm_fsm_process(msg); + rc = emm_fsm_process(user, msg); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/EMM/SAP/emm_reg.h b/openair3/NAS/UE/EMM/SAP/emm_reg.h index 08d28b67db83757d885f4ec97fdea6e48a4cb770..9cd1132c7a333f148625db8049d6847289b8da97 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_reg.h +++ b/openair3/NAS/UE/EMM/SAP/emm_reg.h @@ -42,6 +42,7 @@ Description Defines the EMMREG Service Access Point that provides #define __EMM_REG_H__ #include "emm_regDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -59,8 +60,8 @@ Description Defines the EMMREG Service Access Point that provides /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void emm_reg_initialize(void); +void emm_reg_initialize(nas_user_t *user); -int emm_reg_send(const emm_reg_t *msg); +int emm_reg_send(nas_user_t *user, const emm_reg_t *msg); #endif /* __EMM_REG_H__*/ diff --git a/openair3/NAS/UE/EMM/SAP/emm_sap.c b/openair3/NAS/UE/EMM/SAP/emm_sap.c index d8312ee74cb859e95c2905cb50a973ec23dcb839..429518d475c2c47e20ee86f215d38985de6fd6de 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_sap.c +++ b/openair3/NAS/UE/EMM/SAP/emm_sap.c @@ -46,6 +46,7 @@ Description Defines the EMM Service Access Points at which the EPS #include "emm_reg.h" #include "emm_esm.h" #include "emm_as.h" +#include "user_defs.h" /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ @@ -73,13 +74,13 @@ Description Defines the EMM Service Access Points at which the EPS ** Others: NONE ** ** ** ***************************************************************************/ -void emm_sap_initialize(void) +void emm_sap_initialize(nas_user_t *user) { LOG_FUNC_IN; - emm_reg_initialize(); + emm_reg_initialize(user); emm_esm_initialize(); - emm_as_initialize(); + emm_as_initialize(user); LOG_FUNC_OUT; } @@ -98,7 +99,7 @@ void emm_sap_initialize(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_sap_send(emm_sap_t *msg) +int emm_sap_send(nas_user_t *user, emm_sap_t *msg) { int rc = RETURNerror; @@ -111,17 +112,17 @@ int emm_sap_send(emm_sap_t *msg) (primitive < (emm_primitive_t)EMMREG_PRIMITIVE_MAX) ) { /* Forward to the EMMREG-SAP */ msg->u.emm_reg.primitive = primitive; - rc = emm_reg_send(&msg->u.emm_reg); + rc = emm_reg_send(user, &msg->u.emm_reg); } else if ( (primitive > (emm_primitive_t)EMMESM_PRIMITIVE_MIN) && (primitive < (emm_primitive_t)EMMESM_PRIMITIVE_MAX) ) { /* Forward to the EMMESM-SAP */ msg->u.emm_esm.primitive = primitive; - rc = emm_esm_send(&msg->u.emm_esm); + rc = emm_esm_send(user, &msg->u.emm_esm); } else if ( (primitive > (emm_primitive_t)EMMAS_PRIMITIVE_MIN) && (primitive < (emm_primitive_t)EMMAS_PRIMITIVE_MAX) ) { /* Forward to the EMMAS-SAP */ msg->u.emm_as.primitive = primitive; - rc = emm_as_send(&msg->u.emm_as); + rc = emm_as_send(user, &msg->u.emm_as); } else { LOG_TRACE(WARNING, "EMM-SAP - Out of range primitive (%d)", primitive); diff --git a/openair3/NAS/UE/EMM/SAP/emm_sap.h b/openair3/NAS/UE/EMM/SAP/emm_sap.h index f27e8d4e5832fb797fedb3f992460568d1e0a8b8..b84fd7808b4bf8ae217107041522dd22b2eabf95 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_sap.h +++ b/openair3/NAS/UE/EMM/SAP/emm_sap.h @@ -46,6 +46,7 @@ Description Defines the EMM Service Access Points at which the EPS #include "emm_regDef.h" #include "emm_esmDef.h" #include "emm_asDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -156,8 +157,8 @@ typedef struct emm_sap_s { /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void emm_sap_initialize(void); +void emm_sap_initialize(nas_user_t *user); -int emm_sap_send(emm_sap_t *msg); +int emm_sap_send(nas_user_t *user, emm_sap_t *msg); #endif /* __EMM_SAP_H__*/ diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index f27eb7b4afa87a25a76e08beb95f4a2aa6607b9c..0991fb22bb4ff6a8a68aa7aa25e28141c3448229 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -64,6 +64,7 @@ Description Defines the security mode control EMM procedure executed by the # include "assertions.h" #include "secu_defs.h" #include "msc.h" +#include "SecurityModeControl.h" #if defined(NAS_BUILT_IN_UE) #include "nas_itti_messaging.h" @@ -92,13 +93,6 @@ static int _security_knas_int(const OctetString *kasme, OctetString *knas_int, static int _security_kenb(const OctetString *kasme, OctetString *kenb, uint32_t count); -/* - * Internal data used for security mode control procedure - */ -static struct { - OctetString kenb; /* eNodeB security key */ -} _security_data; - static void _security_release(emm_security_context_t *ctx); /* @@ -145,7 +139,7 @@ static void _security_release(emm_security_context_t *ctx); ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_security_mode_command(int native_ksi, int ksi, +int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, int seea, int seia, int reea, int reia, int imeisv_request) { LOG_FUNC_IN; @@ -153,18 +147,19 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, int rc = RETURNerror; int emm_cause = EMM_CAUSE_SUCCESS; int security_context_is_new = FALSE; + security_data_t *security_data = user->security_data; LOG_TRACE(INFO, "EMM-PROC - Security mode control requested (ksi=%d)", ksi); /* Delete any previously stored RAND and RES and stop timer T3416 */ - (void) emm_proc_authentication_delete(); + (void) emm_proc_authentication_delete(user); /* * Check the replayed UE security capabilities */ - uint8_t eea = (0x80 >> _emm_data.security->capability.eps_encryption); - uint8_t eia = (0x80 >> _emm_data.security->capability.eps_integrity); + uint8_t eea = (0x80 >> user->emm_data->security->capability.eps_encryption); + uint8_t eia = (0x80 >> user->emm_data->security->capability.eps_integrity); if ( (reea != eea) || (reia != eia) ) { LOG_TRACE(WARNING, "EMM-PROC - Replayed UE security capabilities " @@ -180,7 +175,7 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, /* * Check the non-current EPS security context */ - else if (_emm_data.non_current == NULL) { + else if (user->emm_data->non_current == NULL) { LOG_TRACE(WARNING, "EMM-PROC - Non-current EPS security context " "is not valid"); emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED; @@ -191,53 +186,53 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, else { LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context seea=%u seia=%u", seea, seia); /* Update selected cyphering and integrity algorithms */ - //LG COMENTED _emm_data.non_current->capability.encryption = seea; - //LG COMENTED _emm_data.non_current->capability.integrity = seia; + //LG COMENTED user->emm_data->non_current->capability.encryption = seea; + //LG COMENTED user->emm_data->non_current->capability.integrity = seia; - _emm_data.non_current->selected_algorithms.encryption = seea; - _emm_data.non_current->selected_algorithms.integrity = seia; + user->emm_data->non_current->selected_algorithms.encryption = seea; + user->emm_data->non_current->selected_algorithms.integrity = seia; /* Derive the NAS cyphering key */ - if (_emm_data.non_current->knas_enc.value == NULL) { - _emm_data.non_current->knas_enc.value = + if (user->emm_data->non_current->knas_enc.value == NULL) { + user->emm_data->non_current->knas_enc.value = (uint8_t *)calloc(1,AUTH_KNAS_ENC_SIZE); - _emm_data.non_current->knas_enc.length = AUTH_KNAS_ENC_SIZE; + user->emm_data->non_current->knas_enc.length = AUTH_KNAS_ENC_SIZE; } - if (_emm_data.non_current->knas_enc.value != NULL) { + if (user->emm_data->non_current->knas_enc.value != NULL) { LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context knas_enc"); - rc = _security_knas_enc(&_emm_data.non_current->kasme, - &_emm_data.non_current->knas_enc, seea); + rc = _security_knas_enc(&user->emm_data->non_current->kasme, + &user->emm_data->non_current->knas_enc, seea); } /* Derive the NAS integrity key */ - if (_emm_data.non_current->knas_int.value == NULL) { - _emm_data.non_current->knas_int.value = + if (user->emm_data->non_current->knas_int.value == NULL) { + user->emm_data->non_current->knas_int.value = (uint8_t *)calloc(1,AUTH_KNAS_INT_SIZE); - _emm_data.non_current->knas_int.length = AUTH_KNAS_INT_SIZE; + user->emm_data->non_current->knas_int.length = AUTH_KNAS_INT_SIZE; } - if (_emm_data.non_current->knas_int.value != NULL) { + if (user->emm_data->non_current->knas_int.value != NULL) { if (rc != RETURNerror) { LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context knas_int"); - rc = _security_knas_int(&_emm_data.non_current->kasme, - &_emm_data.non_current->knas_int, seia); + rc = _security_knas_int(&user->emm_data->non_current->kasme, + &user->emm_data->non_current->knas_int, seia); } } /* Derive the eNodeB key */ - if (_security_data.kenb.value == NULL) { - _security_data.kenb.value = (uint8_t *)calloc(1,AUTH_KENB_SIZE); - _security_data.kenb.length = AUTH_KENB_SIZE; + if (security_data->kenb.value == NULL) { + security_data->kenb.value = (uint8_t *)calloc(1,AUTH_KENB_SIZE); + security_data->kenb.length = AUTH_KENB_SIZE; } - if (_security_data.kenb.value != NULL) { + if (security_data->kenb.value != NULL) { if (rc != RETURNerror) { LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context kenb"); - // LG COMMENT rc = _security_kenb(&_emm_data.security->kasme, - rc = _security_kenb(&_emm_data.non_current->kasme, - &_security_data.kenb, - *(uint32_t *)(&_emm_data.non_current->ul_count)); + // LG COMMENT rc = _security_kenb(&user->emm_data->security->kasme, + rc = _security_kenb(&user->emm_data->non_current->kasme, + &security_data->kenb, + *(uint32_t *)(&user->emm_data->non_current->ul_count)); } } @@ -248,13 +243,13 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, LOG_TRACE(INFO, "EMM-PROC - NAS security mode command accepted by the UE"); /* Update the current EPS security context */ - if ( native_ksi && (_emm_data.security->type != EMM_KSI_NATIVE) ) { + if ( native_ksi && (user->emm_data->security->type != EMM_KSI_NATIVE) ) { /* The type of security context flag included in the SECURITY * MODE COMMAND message is set to "native security context" and * the UE has a mapped EPS security context as the current EPS * security context */ - if ( (_emm_data.non_current->type == EMM_KSI_NATIVE) && - (_emm_data.non_current->eksi == ksi) ) { + if ( (user->emm_data->non_current->type == EMM_KSI_NATIVE) && + (user->emm_data->non_current->eksi == ksi) ) { /* The KSI matches the non-current native EPS security * context; the UE shall take the non-current native EPS * security context into use which then becomes the @@ -263,36 +258,37 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, LOG_TRACE(INFO, "EMM-PROC - Update Current security context"); /* Release non-current security context */ - _security_release(_emm_data.security); - _emm_data.security = _emm_data.non_current; + _security_release(user->emm_data->security); + user->emm_data->security = user->emm_data->non_current; /* Reset the uplink NAS COUNT counter */ - _emm_data.security->ul_count.overflow = 0; - _emm_data.security->ul_count.seq_num = 0; + user->emm_data->security->ul_count.overflow = 0; + user->emm_data->security->ul_count.seq_num = 0; /* Set new security context indicator */ security_context_is_new = TRUE; } } - if ( !native_ksi && (_emm_data.security->type != EMM_KSI_NATIVE) ) { + if ( !native_ksi && (user->emm_data->security->type != EMM_KSI_NATIVE) ) { /* The type of security context flag included in the SECURITY * MODE COMMAND message is set to "mapped security context" and * the UE has a mapped EPS security context as the current EPS * security context */ - if (ksi != _emm_data.security->eksi) { + if (ksi != user->emm_data->security->eksi) { /* The KSI does not match the current EPS security context; * the UE shall reset the uplink NAS COUNT counter */ LOG_TRACE(INFO, "EMM-PROC - Reset uplink NAS COUNT counter"); - _emm_data.security->ul_count.overflow = 0; - _emm_data.security->ul_count.seq_num = 0; + user->emm_data->security->ul_count.overflow = 0; + user->emm_data->security->ul_count.seq_num = 0; } } - _emm_data.security->selected_algorithms.encryption = seea; - _emm_data.security->selected_algorithms.integrity = seia; + user->emm_data->security->selected_algorithms.encryption = seea; + user->emm_data->security->selected_algorithms.integrity = seia; #if defined(NAS_BUILT_IN_UE) - nas_itti_kenb_refresh_req(_security_data.kenb.value); + nas_itti_kenb_refresh_req(security_data->kenb.value); #endif + } /* * NAS security mode command not accepted by the UE @@ -302,17 +298,17 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED; /* Release security mode control internal data */ - if (_security_data.kenb.value) { - free(_security_data.kenb.value); - _security_data.kenb.value = NULL; - _security_data.kenb.length = 0; + if (security_data->kenb.value) { + free(security_data->kenb.value); + security_data->kenb.value = NULL; + security_data->kenb.length = 0; } } } /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ - rc = emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL); + rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); if (rc != RETURNok) { LOG_TRACE(WARNING, @@ -326,15 +322,15 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, */ emm_sap_t emm_sap; emm_sap.primitive = EMMAS_SECURITY_RES; - emm_sap.u.emm_as.u.security.guti = _emm_data.guti; - emm_sap.u.emm_as.u.security.ueid = 0; + emm_sap.u.emm_as.u.security.guti = user->emm_data->guti; + emm_sap.u.emm_as.u.security.ueid = user->ueid; emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_SMC; emm_sap.u.emm_as.u.security.imeisv_request = imeisv_request; emm_sap.u.emm_as.u.security.emm_cause = emm_cause; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - _emm_data.security, security_context_is_new, TRUE); - rc = emm_sap_send(&emm_sap); + user->emm_data->security, security_context_is_new, TRUE); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.h b/openair3/NAS/UE/EMM/SecurityModeControl.h new file mode 100644 index 0000000000000000000000000000000000000000..314c168544dc24564371988bf16f1065ef3f54f6 --- /dev/null +++ b/openair3/NAS/UE/EMM/SecurityModeControl.h @@ -0,0 +1,11 @@ +#ifndef _SECURITYMODECONTROL_H +#define _SECURITYMODECONTROL_H + +/* + * Internal data used for security mode control procedure + */ +typedef struct { + OctetString kenb; /* eNodeB security key */ +} security_data_t; + +#endif diff --git a/openair3/NAS/UE/EMM/ServiceRequestHdl.c b/openair3/NAS/UE/EMM/ServiceRequestHdl.c index 349fce7cad19c9cdf358e480156994a10bcb0b91..93e66efdbdb2ae7ad387403fa58f60f08d745204 100644 --- a/openair3/NAS/UE/EMM/ServiceRequestHdl.c +++ b/openair3/NAS/UE/EMM/ServiceRequestHdl.c @@ -67,11 +67,6 @@ Description Defines the service request EMM procedure executed by the * Internal data handled by the service request procedure in the UE * -------------------------------------------------------------------------- */ -/* - * Timer handlers - */ -void *_emm_service_t3417_handler(void *); - /* * -------------------------------------------------------------------------- * Internal data handled by the service request procedure in the MME @@ -109,14 +104,16 @@ void *_emm_service_t3417_handler(void *); ** Others: None ** ** ** ***************************************************************************/ -void *_emm_service_t3417_handler(void *args) +void *emm_service_t3417_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - T3417 timer expired"); /* Stop timer T3417 */ - T3417.id = nas_timer_stop(T3417.id); + emm_timers->T3417.id = nas_timer_stop(emm_timers->T3417.id); LOG_FUNC_RETURN(NULL); } diff --git a/openair3/NAS/UE/EMM/TrackingAreaUpdate.c b/openair3/NAS/UE/EMM/TrackingAreaUpdate.c index 50a440951b3bb1c8cd69d23d0c92bd2e2ac67bc9..bafddaf31739edf8f07cab807fb92215f91e73e6 100644 --- a/openair3/NAS/UE/EMM/TrackingAreaUpdate.c +++ b/openair3/NAS/UE/EMM/TrackingAreaUpdate.c @@ -67,10 +67,6 @@ Description Defines the tracking area update EMM procedure executed by the * Internal data handled by the tracking area update procedure in the UE * -------------------------------------------------------------------------- */ -/* - * Timer handlers - */ -void *_emm_tau_t3430_handler(void *); /* * -------------------------------------------------------------------------- @@ -110,14 +106,16 @@ void *_emm_tau_t3430_handler(void *); ** Others: None ** ** ** ***************************************************************************/ -void *_emm_tau_t3430_handler(void *args) +void *emm_tau_t3430_handler(void *args) { LOG_FUNC_IN; + nas_user_t *user = args; + emm_timers_t *emm_timers = user->emm_data->emm_timers; LOG_TRACE(WARNING, "EMM-PROC - T3430 timer expired"); /* Stop timer T3430 */ - T3430.id = nas_timer_stop(T3430.id); + emm_timers->T3430.id = nas_timer_stop(emm_timers->T3430.id); LOG_FUNC_RETURN(NULL); } diff --git a/openair3/NAS/UE/EMM/emmData.h b/openair3/NAS/UE/EMM/emmData.h index df89fb0c8e04937c4d0243b49dca97a2de55d9ed..84e58bb963023f393b3d6333eb743d4753b04455 100644 --- a/openair3/NAS/UE/EMM/emmData.h +++ b/openair3/NAS/UE/EMM/emmData.h @@ -47,6 +47,7 @@ Description Defines internal private data handled by EPS Mobility #include "nas_timer.h" #include "esmData.h" +#include "emm_proc_defs.h" @@ -93,6 +94,29 @@ Description Defines internal private data handled by EPS Mobility /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ +/* + * Internal data used for attach procedure + */ + +#define EMM_ATTACH_COUNTER_MAX 5 + +typedef struct { + unsigned int attempt_count; /* Counter used to limit the number of + * subsequently rejected attach attempts */ +} emm_attach_data_t; + +/* + * Internal data used for detach procedure + */ +typedef struct { +#define EMM_DETACH_COUNTER_MAX 5 + unsigned int count; /* Counter used to limit the number of + * subsequently detach attempts */ + int switch_off; /* UE switch-off indicator */ + emm_proc_detach_type_t type; /* Type of the detach procedure + * currently in progress */ +} emm_detach_data_t; + /* * -------------------------------------------------------------------------- * EPS NAS security context handled by EPS Mobility Management sublayer in @@ -197,6 +221,20 @@ typedef struct emm_nvdata_s { PLMN_LIST_T(EMM_DATA_EPLMN_MAX) eplmn; } emm_nvdata_t; +typedef struct { + struct nas_timer_t T3402; /* attach failure timer */ + struct nas_timer_t T3410; /* attach timer */ + struct nas_timer_t T3411; /* attach restart timer */ + struct nas_timer_t T3412; /* periodic tracking area update timer */ + struct nas_timer_t T3416; /* EPS authentication challenge timer */ + struct nas_timer_t T3417; /* Service request timer */ + struct nas_timer_t T3418; /* MAC authentication failure timer */ + struct nas_timer_t T3420; /* Synch authentication failure timer */ + struct nas_timer_t T3421; /* Detach timer */ + struct nas_timer_t T3430; /* tracking area update timer */ + struct nas_timer_t T3423; /* E-UTRAN deactivate ISR timer */ +} emm_timers_t; + /* * Structure of the EMM data * ------------------------- @@ -324,7 +362,13 @@ typedef struct emm_data_s { */ emm_security_context_t *security; /* current security context */ emm_security_context_t *non_current; /* non-current security context */ - + /* + * EPS mobility management timers – UE side + * ---------------------------------------- + */ + emm_timers_t *emm_timers; + emm_detach_data_t *emm_detach_data; + emm_attach_data_t *emm_attach_data; } emm_data_t; @@ -333,18 +377,6 @@ typedef struct emm_data_s { /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ -/* - * -------------------------------------------------------------------------- - * EPS mobility management data (used within EMM only) - * -------------------------------------------------------------------------- - */ -emm_data_t _emm_data; - -/* - * -------------------------------------------------------------------------- - * EPS mobility management timers – UE side - * -------------------------------------------------------------------------- - */ #define T3402_DEFAULT_VALUE 720 /* 12 minutes */ #define T3410_DEFAULT_VALUE 15 /* 15 seconds */ #define T3411_DEFAULT_VALUE 10 /* 10 seconds */ @@ -359,19 +391,6 @@ emm_data_t _emm_data; #define T3430_DEFAULT_VALUE 15 /* 15 seconds */ #define T3440_DEFAULT_VALUE 10 /* 10 seconds */ -struct nas_timer_t T3402; /* attach failure timer */ -struct nas_timer_t T3410; /* attach timer */ -struct nas_timer_t T3411; /* attach restart timer */ -struct nas_timer_t T3412; /* periodic tracking area update timer */ -struct nas_timer_t T3416; /* EPS authentication challenge timer */ -struct nas_timer_t T3417; /* Service request timer */ -struct nas_timer_t T3418; /* MAC authentication failure timer */ -struct nas_timer_t T3420; /* Synch authentication failure timer */ -struct nas_timer_t T3421; /* Detach timer */ -struct nas_timer_t T3430; /* tracking area update timer */ - -struct nas_timer_t T3423; /* E-UTRAN deactivate ISR timer */ - /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ diff --git a/openair3/NAS/UE/EMM/emm_fsm_defs.h b/openair3/NAS/UE/EMM/emm_fsm_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..4e5b4a8ee67b82030ad0ccdecde2f25ee88ad7de --- /dev/null +++ b/openair3/NAS/UE/EMM/emm_fsm_defs.h @@ -0,0 +1,42 @@ +#ifndef _EMM_FSM_DEFS_H +#define _EMM_FSM_DEFS_H + +/****************************************************************************/ +/************************ G L O B A L T Y P E S ************************/ +/****************************************************************************/ + +/* + * States of the EPS Mobility Management sublayer + * ---------------------------------------------- + * The EMM protocol of the UE and the network is described by means of two + * different state machines. + */ +typedef enum { + EMM_INVALID, + EMM_NULL, + EMM_DEREGISTERED, + EMM_REGISTERED, + EMM_DEREGISTERED_INITIATED, + EMM_DEREGISTERED_NORMAL_SERVICE, + EMM_DEREGISTERED_LIMITED_SERVICE, + EMM_DEREGISTERED_ATTEMPTING_TO_ATTACH, + EMM_DEREGISTERED_PLMN_SEARCH, + EMM_DEREGISTERED_NO_IMSI, + EMM_DEREGISTERED_ATTACH_NEEDED, + EMM_DEREGISTERED_NO_CELL_AVAILABLE, + EMM_REGISTERED_INITIATED, + EMM_REGISTERED_NORMAL_SERVICE, + EMM_REGISTERED_ATTEMPTING_TO_UPDATE, + EMM_REGISTERED_LIMITED_SERVICE, + EMM_REGISTERED_PLMN_SEARCH, + EMM_REGISTERED_UPDATE_NEEDED, + EMM_REGISTERED_NO_CELL_AVAILABLE, + EMM_REGISTERED_ATTEMPTING_TO_UPDATE_MM, + EMM_REGISTERED_IMSI_DETACH_INITIATED, + EMM_TRACKING_AREA_UPDATING_INITIATED, + EMM_SERVICE_REQUEST_INITIATED, + EMM_STATE_MAX +} emm_fsm_state_t; + + +#endif diff --git a/openair3/NAS/UE/EMM/emm_main.c b/openair3/NAS/UE/EMM/emm_main.c index 2eb4d8fa24d6b18c1d7e8f88d01bbfc00961c2ca..8f3ed17e4cae7e03f61d9d4246ed1398ca9f358c 100644 --- a/openair3/NAS/UE/EMM/emm_main.c +++ b/openair3/NAS/UE/EMM/emm_main.c @@ -39,8 +39,10 @@ Description Defines the EPS Mobility Management procedure call manager, #include "emm_main.h" #include "nas_log.h" +#include "utils.h" #include "emmData.h" #include "MobileIdentity.h" +#include "emm_proc_defs.h" #include "memory.h" #include "usim_api.h" @@ -63,27 +65,58 @@ static int _emm_main_get_imei(imei_t *imei, const char *imei_str); static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2); -static const char *_emm_main_get_plmn(const plmn_t *plmn, int index, +static const char *_emm_main_get_plmn(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, int format, size_t *size); -static int _emm_main_get_plmn_index(const char *plmn, int format); - -/* - * USIM application data - */ -static usim_data_t _usim_data; +static int _emm_main_get_plmn_index(emm_plmn_list_t *emm_plmn_list, const char *plmn, int format); /* * Callback executed whenever a change in the network has to be notified * to the user application */ static emm_indication_callback_t _emm_main_user_callback; -static int _emm_main_callback(int); +static int _emm_main_callback(user_api_id_t *user_api_id, emm_data_t *emm_data, int size); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ + /* + * Initialize EMM timers + */ +void _emm_timers_initialize(emm_timers_t *emm_timers) { + emm_timers->T3410.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3410.sec = T3410_DEFAULT_VALUE; + emm_timers->T3411.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3411.sec = T3411_DEFAULT_VALUE; + emm_timers->T3402.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3402.sec = T3402_DEFAULT_VALUE; + emm_timers->T3416.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3416.sec = T3416_DEFAULT_VALUE; + emm_timers->T3417.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3417.sec = T3417_DEFAULT_VALUE; + emm_timers->T3418.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3418.sec = T3418_DEFAULT_VALUE; + emm_timers->T3420.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3420.sec = T3420_DEFAULT_VALUE; + emm_timers->T3421.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3421.sec = T3421_DEFAULT_VALUE; + emm_timers->T3423.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3423.sec = T3423_DEFAULT_VALUE; + emm_timers->T3430.id = NAS_TIMER_INACTIVE_ID; + emm_timers->T3430.sec = T3430_DEFAULT_VALUE; +} + +void _emm_attach_initialize(emm_attach_data_t *emm_attach_data) { + emm_attach_data->attempt_count = 0; +} + +void _emm_detach_initialize(emm_detach_data_t *emm_detach) { + emm_detach->count = 0; + emm_detach->switch_off = FALSE; + emm_detach->type = EMM_DETACH_TYPE_RESERVED; +} + /**************************************************************************** ** ** ** Name: emm_main_initialize() ** @@ -93,76 +126,74 @@ static int _emm_main_callback(int); ** Inputs: cb: The user notification callback ** ** imei: The IMEI read from the UE's non-volatile ** ** memory ** - ** Others: _usim_data ** ** ** ** Outputs: None ** ** Return: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -void emm_main_initialize(emm_indication_callback_t cb, const char *imei) +void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const char *imei) { LOG_FUNC_IN; - + user->emm_data = calloc_or_fail(sizeof(emm_data_t)); /* USIM validity indicator */ - _emm_data.usim_is_valid = FALSE; + user->emm_data->usim_is_valid = FALSE; /* The IMEI read from the UE's non-volatile memory */ - _emm_data.imei = (imei_t *)malloc(sizeof(imei_t)); - _emm_data.imei->length = _emm_main_get_imei(_emm_data.imei, imei); + user->emm_data->imei = (imei_t *)malloc(sizeof(imei_t)); + user->emm_data->imei->length = _emm_main_get_imei(user->emm_data->imei, imei); /* The IMSI, valid only if USIM is present */ - _emm_data.imsi = NULL; + user->emm_data->imsi = NULL; /* EPS location information */ - _emm_data.guti = NULL; - _emm_data.tai = NULL; - _emm_data.ltai.n_tais = 0; + user->emm_data->guti = NULL; + user->emm_data->tai = NULL; + user->emm_data->ltai.n_tais = 0; /* EPS Connection Management status */ - _emm_data.ecm_status = ECM_IDLE; + user->emm_data->ecm_status = ECM_IDLE; /* Network selection mode of operation */ - _emm_data.plmn_mode = EMM_DATA_PLMN_AUTO; + user->emm_data->plmn_mode = EMM_DATA_PLMN_AUTO; /* Index of the PLMN manually selected by the user */ - _emm_data.plmn_index = -1; + user->emm_data->plmn_index = -1; /* Selected Radio Access Technology */ - _emm_data.plmn_rat = NET_ACCESS_UNAVAILABLE; + user->emm_data->plmn_rat = NET_ACCESS_UNAVAILABLE; /* Selected PLMN */ - memset(&_emm_data.splmn, 0xFF, sizeof(plmn_t)); - _emm_data.is_rplmn = FALSE; - _emm_data.is_eplmn = FALSE; + memset(&user->emm_data->splmn, 0xFF, sizeof(plmn_t)); + user->emm_data->is_rplmn = FALSE; + user->emm_data->is_eplmn = FALSE; /* Radio Access Technology of the serving cell */ - _emm_data.rat = NET_ACCESS_UNAVAILABLE; + user->emm_data->rat = NET_ACCESS_UNAVAILABLE; /* Network registration status */ - _emm_data.stat = NET_REG_STATE_OFF; - _emm_data.is_attached = FALSE; - _emm_data.is_emergency = FALSE; + user->emm_data->stat = NET_REG_STATE_OFF; + user->emm_data->is_attached = FALSE; + user->emm_data->is_emergency = FALSE; /* Location/Tracking area code */ - _emm_data.tac = 0; // two byte in hexadecimal format + user->emm_data->tac = 0; // two byte in hexadecimal format /* Identifier of the serving cell */ - _emm_data.ci = 0; // four byte in hexadecimal format + user->emm_data->ci = 0; // four byte in hexadecimal format /* List of operators present in the network */ - memset(_emm_data.plist.buffer, 0, EMM_DATA_BUFFER_SIZE + 1); + memset(user->emm_data->plist.buffer, 0, EMM_DATA_BUFFER_SIZE + 1); /* Home PLMN */ - memset(&_emm_data.hplmn, 0xFF, sizeof(plmn_t)); + memset(&user->emm_data->hplmn, 0xFF, sizeof(plmn_t)); /* List of Forbidden PLMNs */ - _emm_data.fplmn.n_plmns = 0; + user->emm_data->fplmn.n_plmns = 0; /* List of Forbidden PLMNs for GPRS service */ - _emm_data.fplmn_gprs.n_plmns = 0; + user->emm_data->fplmn_gprs.n_plmns = 0; /* List of Equivalent HPLMNs */ - _emm_data.ehplmn.n_plmns = 0; + user->emm_data->ehplmn.n_plmns = 0; /* List of user controlled PLMNs */ - _emm_data.plmn.n_plmns = 0; + user->emm_data->plmn.n_plmns = 0; /* List of operator controlled PLMNs */ - _emm_data.oplmn.n_plmns = 0; + user->emm_data->oplmn.n_plmns = 0; /* List of operator network name records */ - _emm_data.n_opnns = 0; + user->emm_data->n_opnns = 0; /* List of Forbidden Tracking Areas */ - _emm_data.ftai.n_tais = 0; + user->emm_data->ftai.n_tais = 0; /* List of Forbidden Tracking Areas for roaming */ - _emm_data.ftai_roaming.n_tais = 0; + user->emm_data->ftai_roaming.n_tais = 0; /* * Get USIM application data */ - _usim_data.usimtestmode = usim_test; - if ( usim_api_read(&_usim_data) != RETURNok ) { + if ( usim_api_read(user->usim_data_store, &user->usim_data) != RETURNok ) { /* The USIM application may not be present or not valid */ LOG_TRACE(WARNING, "EMM-MAIN - Failed to read USIM application data"); } else { @@ -170,138 +201,184 @@ void emm_main_initialize(emm_indication_callback_t cb, const char *imei) /* The USIM application is present and valid */ LOG_TRACE(INFO, "EMM-MAIN - USIM application data successfully read"); - _emm_data.usim_is_valid = TRUE; + user->emm_data->usim_is_valid = TRUE; + + /* print keys (for debugging) */ + { + char usim_api_k[256]; + char opc[256]; + sprintf(usim_api_k, + "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x " + "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x", + user->usim_data.keys.usim_api_k[0], + user->usim_data.keys.usim_api_k[1], + user->usim_data.keys.usim_api_k[2], + user->usim_data.keys.usim_api_k[3], + user->usim_data.keys.usim_api_k[4], + user->usim_data.keys.usim_api_k[5], + user->usim_data.keys.usim_api_k[6], + user->usim_data.keys.usim_api_k[7], + user->usim_data.keys.usim_api_k[8], + user->usim_data.keys.usim_api_k[9], + user->usim_data.keys.usim_api_k[10], + user->usim_data.keys.usim_api_k[11], + user->usim_data.keys.usim_api_k[12], + user->usim_data.keys.usim_api_k[13], + user->usim_data.keys.usim_api_k[14], + user->usim_data.keys.usim_api_k[15]); + sprintf(opc, + "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x " + "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x", + user->usim_data.keys.opc[0], + user->usim_data.keys.opc[1], + user->usim_data.keys.opc[2], + user->usim_data.keys.opc[3], + user->usim_data.keys.opc[4], + user->usim_data.keys.opc[5], + user->usim_data.keys.opc[6], + user->usim_data.keys.opc[7], + user->usim_data.keys.opc[8], + user->usim_data.keys.opc[9], + user->usim_data.keys.opc[10], + user->usim_data.keys.opc[11], + user->usim_data.keys.opc[12], + user->usim_data.keys.opc[13], + user->usim_data.keys.opc[14], + user->usim_data.keys.opc[15]); + LOG_TRACE(INFO, "EMM-MAIN - usim_api_k: %s", usim_api_k); + LOG_TRACE(INFO, "EMM-MAIN - opc: %s", opc); + } /* Get the Home PLMN derived from the IMSI */ - _emm_data.hplmn.MCCdigit1 = _usim_data.imsi.u.num.digit1; - _emm_data.hplmn.MCCdigit2 = _usim_data.imsi.u.num.digit2; - _emm_data.hplmn.MCCdigit3 = _usim_data.imsi.u.num.digit3; - _emm_data.hplmn.MNCdigit1 = _usim_data.imsi.u.num.digit4; - _emm_data.hplmn.MNCdigit2 = _usim_data.imsi.u.num.digit5; - _emm_data.hplmn.MNCdigit3 = _usim_data.imsi.u.num.digit6; + user->emm_data->hplmn.MCCdigit1 = user->usim_data.imsi.u.num.digit1; + user->emm_data->hplmn.MCCdigit2 = user->usim_data.imsi.u.num.digit2; + user->emm_data->hplmn.MCCdigit3 = user->usim_data.imsi.u.num.digit3; + user->emm_data->hplmn.MNCdigit1 = user->usim_data.imsi.u.num.digit4; + user->emm_data->hplmn.MNCdigit2 = user->usim_data.imsi.u.num.digit5; + user->emm_data->hplmn.MNCdigit3 = user->usim_data.imsi.u.num.digit6; /* Get the list of forbidden PLMNs */ for (i=0; (i < EMM_DATA_FPLMN_MAX) && (i < USIM_FPLMN_MAX); i++) { - if ( PLMN_IS_VALID(_usim_data.fplmn[i]) ) { - _emm_data.fplmn.plmn[i] = _usim_data.fplmn[i]; - _emm_data.fplmn.n_plmns += 1; + if ( PLMN_IS_VALID(user->usim_data.fplmn[i]) ) { + user->emm_data->fplmn.plmn[i] = user->usim_data.fplmn[i]; + user->emm_data->fplmn.n_plmns += 1; } } /* Get the list of Equivalent HPLMNs */ for (i=0; (i < EMM_DATA_EHPLMN_MAX) && (i < USIM_EHPLMN_MAX); i++) { - if ( PLMN_IS_VALID(_usim_data.ehplmn[i]) ) { - _emm_data.ehplmn.plmn[i] = _usim_data.ehplmn[i]; - _emm_data.ehplmn.n_plmns += 1; + if ( PLMN_IS_VALID(user->usim_data.ehplmn[i]) ) { + user->emm_data->ehplmn.plmn[i] = user->usim_data.ehplmn[i]; + user->emm_data->ehplmn.n_plmns += 1; } } /* Get the list of User controlled PLMN Selector */ for (i=0; (i < EMM_DATA_PLMN_MAX) && (i < USIM_PLMN_MAX); i++) { - if ( PLMN_IS_VALID(_usim_data.plmn[i].plmn) ) { - _emm_data.plmn.plmn[i] = _usim_data.plmn[i].plmn; - _emm_data.userAcT[i] = _usim_data.plmn[i].AcT; - _emm_data.plmn.n_plmns += 1; + if ( PLMN_IS_VALID(user->usim_data.plmn[i].plmn) ) { + user->emm_data->plmn.plmn[i] = user->usim_data.plmn[i].plmn; + user->emm_data->userAcT[i] = user->usim_data.plmn[i].AcT; + user->emm_data->plmn.n_plmns += 1; } } /* Get the list of Operator controlled PLMN Selector */ for (i=0; (i < EMM_DATA_OPLMN_MAX) && (i < USIM_OPLMN_MAX); i++) { - if ( PLMN_IS_VALID(_usim_data.oplmn[i].plmn) ) { - _emm_data.oplmn.plmn[i] = _usim_data.oplmn[i].plmn; - _emm_data.operAcT[i] = _usim_data.oplmn[i].AcT; - _emm_data.oplmn.n_plmns += 1; + if ( PLMN_IS_VALID(user->usim_data.oplmn[i].plmn) ) { + user->emm_data->oplmn.plmn[i] = user->usim_data.oplmn[i].plmn; + user->emm_data->operAcT[i] = user->usim_data.oplmn[i].AcT; + user->emm_data->oplmn.n_plmns += 1; } } /* Get the list of Operator network name records */ for (i=0; (i < EMM_DATA_OPNN_MAX) && (i < USIM_OPL_MAX); i++) { - if ( PLMN_IS_VALID(_usim_data.opl[i].plmn) ) { - int pnn_id = _usim_data.opl[i].record_id; - _emm_data.opnn[i].plmn = &_usim_data.opl[i].plmn; - _emm_data.opnn[i].fullname = (char *)_usim_data.pnn[pnn_id].fullname.value; - _emm_data.opnn[i].shortname = (char *)_usim_data.pnn[pnn_id].shortname.value; - _emm_data.n_opnns += 1; + if ( PLMN_IS_VALID(user->usim_data.opl[i].plmn) ) { + int pnn_id = user->usim_data.opl[i].record_id; + user->emm_data->opnn[i].plmn = &user->usim_data.opl[i].plmn; + user->emm_data->opnn[i].fullname = (char *)user->usim_data.pnn[pnn_id].fullname.value; + user->emm_data->opnn[i].shortname = (char *)user->usim_data.pnn[pnn_id].shortname.value; + user->emm_data->n_opnns += 1; } } /* TODO: Get the Higher Priority PLMN search period parameter */ /* Get the EPS location information */ - if (PLMN_IS_VALID(_usim_data.epsloci.guti.gummei.plmn)) { - _emm_data.guti = &_usim_data.epsloci.guti; + if (PLMN_IS_VALID(user->usim_data.epsloci.guti.gummei.plmn)) { + user->emm_data->guti = &user->usim_data.epsloci.guti; } - if (TAI_IS_VALID(_usim_data.epsloci.tai)) { - _emm_data.tai = &_usim_data.epsloci.tai; + if (TAI_IS_VALID(user->usim_data.epsloci.tai)) { + user->emm_data->tai = &user->usim_data.epsloci.tai; } - _emm_data.status = _usim_data.epsloci.status; + user->emm_data->status = user->usim_data.epsloci.status; /* Get NAS configuration parameters */ - _emm_data.NAS_SignallingPriority = - _usim_data.nasconfig.NAS_SignallingPriority.value[0]; - _emm_data.NMO_I_Behaviour = _usim_data.nasconfig.NMO_I_Behaviour.value[0]; - _emm_data.AttachWithImsi = _usim_data.nasconfig.AttachWithImsi.value[0]; - _emm_data.MinimumPeriodicSearchTimer = - _usim_data.nasconfig.MinimumPeriodicSearchTimer.value[0]; - _emm_data.ExtendedAccessBarring = - _usim_data.nasconfig.ExtendedAccessBarring.value[0]; - _emm_data.Timer_T3245_Behaviour = - _usim_data.nasconfig.Timer_T3245_Behaviour.value[0]; + user->emm_data->NAS_SignallingPriority = + user->usim_data.nasconfig.NAS_SignallingPriority.value[0]; + user->emm_data->NMO_I_Behaviour = user->usim_data.nasconfig.NMO_I_Behaviour.value[0]; + user->emm_data->AttachWithImsi = user->usim_data.nasconfig.AttachWithImsi.value[0]; + user->emm_data->MinimumPeriodicSearchTimer = + user->usim_data.nasconfig.MinimumPeriodicSearchTimer.value[0]; + user->emm_data->ExtendedAccessBarring = + user->usim_data.nasconfig.ExtendedAccessBarring.value[0]; + user->emm_data->Timer_T3245_Behaviour = + user->usim_data.nasconfig.Timer_T3245_Behaviour.value[0]; /* * Get EPS NAS security context */ /* Create NAS security context */ - _emm_data.security = + user->emm_data->security = (emm_security_context_t *)malloc(sizeof(emm_security_context_t)); - if (_emm_data.security != NULL) { - memset(_emm_data.security, 0, sizeof(emm_security_context_t)); + if (user->emm_data->security != NULL) { + memset(user->emm_data->security, 0, sizeof(emm_security_context_t)); /* Type of security context */ - if (_usim_data.securityctx.KSIasme.value[0] != + if (user->usim_data.securityctx.KSIasme.value[0] != USIM_KSI_NOT_AVAILABLE) { - _emm_data.security->type = EMM_KSI_NATIVE; + user->emm_data->security->type = EMM_KSI_NATIVE; } else { - _emm_data.security->type = EMM_KSI_NOT_AVAILABLE; + user->emm_data->security->type = EMM_KSI_NOT_AVAILABLE; } /* EPS key set identifier */ - _emm_data.security->eksi = _usim_data.securityctx.KSIasme.value[0]; + user->emm_data->security->eksi = user->usim_data.securityctx.KSIasme.value[0]; /* ASME security key */ - _emm_data.security->kasme.length = - _usim_data.securityctx.Kasme.length; - _emm_data.security->kasme.value = - (uint8_t *)malloc(_emm_data.security->kasme.length); - - if (_emm_data.security->kasme.value) { - memcpy(_emm_data.security->kasme.value, - _usim_data.securityctx.Kasme.value, - _emm_data.security->kasme.length); + user->emm_data->security->kasme.length = + user->usim_data.securityctx.Kasme.length; + user->emm_data->security->kasme.value = + (uint8_t *)malloc(user->emm_data->security->kasme.length); + + if (user->emm_data->security->kasme.value) { + memcpy(user->emm_data->security->kasme.value, + user->usim_data.securityctx.Kasme.value, + user->emm_data->security->kasme.length); } /* Downlink count parameter */ - if (_usim_data.securityctx.dlNAScount.length <= sizeof(uint32_t)) { - memcpy(&_emm_data.security->dl_count, - _usim_data.securityctx.dlNAScount.value, - _usim_data.securityctx.dlNAScount.length); + if (user->usim_data.securityctx.dlNAScount.length <= sizeof(uint32_t)) { + memcpy(&user->emm_data->security->dl_count, + user->usim_data.securityctx.dlNAScount.value, + user->usim_data.securityctx.dlNAScount.length); } /* Uplink count parameter */ - if (_usim_data.securityctx.ulNAScount.length <= sizeof(uint32_t)) { - memcpy(&_emm_data.security->ul_count, - _usim_data.securityctx.ulNAScount.value, - _usim_data.securityctx.ulNAScount.length); + if (user->usim_data.securityctx.ulNAScount.length <= sizeof(uint32_t)) { + memcpy(&user->emm_data->security->ul_count, + user->usim_data.securityctx.ulNAScount.value, + user->usim_data.securityctx.ulNAScount.length); } /* Ciphering algorithm */ - _emm_data.security->capability.eps_encryption = - ((_usim_data.securityctx.algorithmID.value[0] >> 4) & 0xf); + user->emm_data->security->capability.eps_encryption = + ((user->usim_data.securityctx.algorithmID.value[0] >> 4) & 0xf); /* Identity protection algorithm */ - _emm_data.security->capability.eps_integrity = - (_usim_data.securityctx.algorithmID.value[0] & 0xf); + user->emm_data->security->capability.eps_integrity = + (user->usim_data.securityctx.algorithmID.value[0] & 0xf); /* NAS integrity and cyphering keys are not available */ } else { LOG_TRACE(WARNING, @@ -311,78 +388,65 @@ void emm_main_initialize(emm_indication_callback_t cb, const char *imei) /* * Get EMM data from the UE's non-volatile memory */ - memset(&_emm_data.nvdata.rplmn, 0xFF, sizeof(plmn_t)); - _emm_data.nvdata.eplmn.n_plmns = 0; - /* Get EMM data pathname */ - char *path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME); + memset(&user->emm_data->nvdata.rplmn, 0xFF, sizeof(plmn_t)); + user->emm_data->nvdata.eplmn.n_plmns = 0; - if (path == NULL) { - LOG_TRACE(ERROR, "EMM-MAIN - Failed to get EMM data pathname"); - } else { - /* Get EMM data stored in the non-volatile memory device */ - int rc = memory_read(path, &_emm_data.nvdata, sizeof(emm_nvdata_t)); + /* Get EMM data stored in the non-volatile memory device */ + int rc = memory_read(user->emm_nvdata_store, &user->emm_data->nvdata, sizeof(emm_nvdata_t)); - if (rc != RETURNok) { - LOG_TRACE(ERROR, "EMM-MAIN - Failed to read %s", path); - } else { - /* Check the IMSI */ - LOG_TRACE(INFO, "EMM-MAIN - EMM data successfully read"); - _emm_data.imsi = &_usim_data.imsi; - int imsi_ok = _emm_main_imsi_cmp(&_emm_data.nvdata.imsi, - &_usim_data.imsi); - - if (!imsi_ok) { - LOG_TRACE(WARNING, "EMM-MAIN - IMSI checking failed nvram: " - "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x, " - "usim: %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x", - _emm_data.nvdata.imsi.u.value[0], - _emm_data.nvdata.imsi.u.value[1], - _emm_data.nvdata.imsi.u.value[2], - _emm_data.nvdata.imsi.u.value[3], - _emm_data.nvdata.imsi.u.value[4], - _emm_data.nvdata.imsi.u.value[5], - _emm_data.nvdata.imsi.u.value[6], - _emm_data.nvdata.imsi.u.value[7], - _usim_data.imsi.u.value[0], - _usim_data.imsi.u.value[1], - _usim_data.imsi.u.value[2], - _usim_data.imsi.u.value[3], - _usim_data.imsi.u.value[4], - _usim_data.imsi.u.value[5], - _usim_data.imsi.u.value[6], - _usim_data.imsi.u.value[7]); - memset(&_emm_data.nvdata.rplmn, 0xFF, sizeof(plmn_t)); - _emm_data.nvdata.eplmn.n_plmns = 0; - } - } + if (rc != RETURNok) { + LOG_TRACE(ERROR, "EMM-MAIN - Failed to read %s", user->emm_nvdata_store); + exit(EXIT_FAILURE); + } - free(path); + /* Check the IMSI */ + LOG_TRACE(INFO, "EMM-MAIN - EMM data successfully read"); + user->emm_data->imsi = &user->usim_data.imsi; + int imsi_ok = _emm_main_imsi_cmp(&user->emm_data->nvdata.imsi, + &user->usim_data.imsi); + + if (!imsi_ok) { + LOG_TRACE(WARNING, "EMM-MAIN - IMSI checking failed nvram: " + "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x, " + "usim: %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x", + user->emm_data->nvdata.imsi.u.value[0], + user->emm_data->nvdata.imsi.u.value[1], + user->emm_data->nvdata.imsi.u.value[2], + user->emm_data->nvdata.imsi.u.value[3], + user->emm_data->nvdata.imsi.u.value[4], + user->emm_data->nvdata.imsi.u.value[5], + user->emm_data->nvdata.imsi.u.value[6], + user->emm_data->nvdata.imsi.u.value[7], + user->usim_data.imsi.u.value[0], + user->usim_data.imsi.u.value[1], + user->usim_data.imsi.u.value[2], + user->usim_data.imsi.u.value[3], + user->usim_data.imsi.u.value[4], + user->usim_data.imsi.u.value[5], + user->usim_data.imsi.u.value[6], + user->usim_data.imsi.u.value[7]); + memset(&user->emm_data->nvdata.rplmn, 0xFF, sizeof(plmn_t)); + user->emm_data->nvdata.eplmn.n_plmns = 0; } } /* * Initialize EMM timers */ - T3410.id = NAS_TIMER_INACTIVE_ID; - T3410.sec = T3410_DEFAULT_VALUE; - T3411.id = NAS_TIMER_INACTIVE_ID; - T3411.sec = T3411_DEFAULT_VALUE; - T3402.id = NAS_TIMER_INACTIVE_ID; - T3402.sec = T3402_DEFAULT_VALUE; - T3416.id = NAS_TIMER_INACTIVE_ID; - T3416.sec = T3416_DEFAULT_VALUE; - T3417.id = NAS_TIMER_INACTIVE_ID; - T3417.sec = T3417_DEFAULT_VALUE; - T3418.id = NAS_TIMER_INACTIVE_ID; - T3418.sec = T3418_DEFAULT_VALUE; - T3420.id = NAS_TIMER_INACTIVE_ID; - T3420.sec = T3420_DEFAULT_VALUE; - T3421.id = NAS_TIMER_INACTIVE_ID; - T3421.sec = T3421_DEFAULT_VALUE; - T3423.id = NAS_TIMER_INACTIVE_ID; - T3423.sec = T3423_DEFAULT_VALUE; - T3430.id = NAS_TIMER_INACTIVE_ID; - T3430.sec = T3430_DEFAULT_VALUE; + user->emm_data->emm_timers = calloc_or_fail(sizeof(emm_timers_t)); + _emm_timers_initialize(user->emm_data->emm_timers); + + /* + * Initialize Internal data used for detach procedure + */ + user->emm_data->emm_detach_data = calloc_or_fail(sizeof(emm_detach_data_t)); + _emm_detach_initialize(user->emm_data->emm_detach_data); + + /* + * Initialize Internal data used for attach procedure + */ + user->emm_data->emm_attach_data = calloc_or_fail(sizeof(emm_attach_data_t)); + _emm_attach_initialize(user->emm_data->emm_attach_data); /* * Initialize the user notification callback @@ -392,7 +456,7 @@ void emm_main_initialize(emm_indication_callback_t cb, const char *imei) /* * Initialize EMM internal data used for UE in idle mode */ - IdleMode_initialize(&_emm_main_callback); + IdleMode_initialize(user, &_emm_main_callback); LOG_FUNC_OUT; } @@ -412,56 +476,16 @@ void emm_main_initialize(emm_indication_callback_t cb, const char *imei) ** Others: None ** ** ** ***************************************************************************/ -void emm_main_cleanup(void) +void emm_main_cleanup(nas_user_t *user) { LOG_FUNC_IN; - if (_emm_data.usim_is_valid) { - /* - * TODO: Update USIM application data - */ -#if 0 - int i; - - /* Update the list of Forbidden PLMNs */ - for (i=0; (i < _emm_data.fplmn.n_plmns) && (i < USIM_FPLMN_MAX); i++) { - _usim_data.fplmn[i] = _emm_data.fplmn.plmn[i]; - } - - /* Update the list of Equivalent HPLMNs */ - for (i=0; (i < _emm_data.ehplmn.n_plmns) && (i < USIM_EHPLMN_MAX); i++) { - _usim_data.ehplmn[i] = _emm_data.ehplmn.plmn[i]; - } - - /* Update the GUTI */ - if (_emm_data.guti) { - _usim_data.epsloci.guti = *(_emm_data.guti); - } - - /* Update the last visited registered TAI */ - if (_emm_data.tai) { - _usim_data.epsloci.tai = *(_emm_data.tai); - } - - /* Update the EPS location information */ - _usim_data.epsloci.status = _emm_data.status; - - if (_emm_data.security && (_emm_data.security->type == EMM_KSI_NATIVE)) { - /* TODO: Update the EPS security context parameters from the full - * native EPS security context */ - } + emm_data_t *emm_data = user->emm_data; + if (emm_data->usim_is_valid) { /* - * Store USIM application data - * - List of forbidden PLMNs + * TODO: Update USIM application data */ - if ( usim_api_write(&_usim_data) != RETURNok ) { - /* The USIM application may not be present or not valid */ - LOG_TRACE(WARNING, "EMM-MAIN - " - "Failed to write USIM application data"); - } - -#endif } /* @@ -469,26 +493,20 @@ void emm_main_cleanup(void) * - Registered PLMN * - List of equivalent PLMNs */ - char *path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME); - - if (path == NULL) { - LOG_TRACE(ERROR, "EMM-MAIN - Failed to get EMM data pathname"); - } else { - int rc = memory_write(path, &_emm_data.nvdata, sizeof(emm_nvdata_t)); + int rc = memory_write(user->emm_nvdata_store, &emm_data->nvdata, sizeof(emm_nvdata_t)); - if (rc != RETURNok) { - LOG_TRACE(ERROR, "EMM-MAIN - Failed to write %s", path); - } + if (rc != RETURNok) { + LOG_TRACE(ERROR, "EMM-MAIN - Failed to write %s", user->emm_nvdata_store); } /* Release dynamically allocated memory */ - if (_emm_data.imei) { - free(_emm_data.imei); - _emm_data.imei = NULL; + if (emm_data->imei) { + free(emm_data->imei); + emm_data->imei = NULL; } - if (_emm_data.security) { - emm_security_context_t *security = _emm_data.security; + if (emm_data->security) { + emm_security_context_t *security = emm_data->security; if (security->kasme.value) { free(security->kasme.value); @@ -508,8 +526,8 @@ void emm_main_cleanup(void) security->knas_int.length = 0; } - free(_emm_data.security); - _emm_data.security = NULL; + free(emm_data->security); + emm_data->security = NULL; } LOG_FUNC_OUT; } @@ -521,17 +539,17 @@ void emm_main_cleanup(void) ** Description: Get the International Mobile Subscriber Identity number ** ** ** ** Inputs: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: Pointer to the IMSI ** ** Others: None ** ** ** ***************************************************************************/ -const imsi_t *emm_main_get_imsi(void) +const imsi_t *emm_main_get_imsi(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (&_emm_data.nvdata.imsi); + LOG_FUNC_RETURN (&emm_data->nvdata.imsi); } /**************************************************************************** @@ -541,17 +559,16 @@ const imsi_t *emm_main_get_imsi(void) ** Description: Get the Mobile Subscriber Dialing Number from the USIM ** ** ** ** Inputs: None ** - ** Others: _usim_data ** ** ** ** Outputs: None ** ** Return: Pointer to the subscriber dialing number ** ** Others: None ** ** ** ***************************************************************************/ -const msisdn_t *emm_main_get_msisdn(void) +const msisdn_t *emm_main_get_msisdn(nas_user_t *user) { LOG_FUNC_IN; - LOG_FUNC_RETURN (&_usim_data.msisdn.number); + LOG_FUNC_RETURN (&user->usim_data.msisdn.number); } /**************************************************************************** @@ -572,32 +589,34 @@ const msisdn_t *emm_main_get_msisdn(void) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ***************************************************************************/ -int emm_main_set_plmn_selection_mode(int mode, int format, +int emm_main_set_plmn_selection_mode(nas_user_t *user, int mode, int format, const network_plmn_t *plmn, int rat) { LOG_FUNC_IN; int index; + emm_data_t *emm_data = user->emm_data; + emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list; LOG_TRACE(INFO, "EMM-MAIN - PLMN selection: mode=%d, format=%d, plmn=%s, " "rat=%d", mode, format, (const char *)&plmn->id, rat); - _emm_data.plmn_mode = mode; + emm_data->plmn_mode = mode; if (mode != EMM_DATA_PLMN_AUTO) { /* Get the index of the PLMN in the list of available PLMNs */ - index = _emm_main_get_plmn_index((const char *)&plmn->id, format); + index = _emm_main_get_plmn_index(emm_plmn_list, (const char *)&plmn->id, format); if (index < 0) { LOG_TRACE(WARNING, "EMM-MAIN - PLMN %s not available", (const char *)&plmn->id); } else { /* Update the manually selected network selection data */ - _emm_data.plmn_index = index; - _emm_data.plmn_rat = rat; + emm_data->plmn_index = index; + emm_data->plmn_rat = rat; } } else { /* @@ -605,7 +624,7 @@ int emm_main_set_plmn_selection_mode(int mode, int format, * register to when switched on; the equivalent PLMNs list shall not be * applied to the user reselection in Automatic Network Selection Mode. */ - index = IdleMode_get_hplmn_index(); + index = IdleMode_get_hplmn_index(emm_plmn_list); } LOG_FUNC_RETURN (index); @@ -619,17 +638,17 @@ int emm_main_set_plmn_selection_mode(int mode, int format, ** operation ** ** ** ** Inputs: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: The value of the network selection mode ** ** Others: None ** ** ** ***************************************************************************/ -int emm_main_get_plmn_selection_mode(void) +int emm_main_get_plmn_selection_mode(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.plmn_mode); + LOG_FUNC_RETURN (emm_data->plmn_mode); } /**************************************************************************** @@ -639,19 +658,19 @@ int emm_main_get_plmn_selection_mode(void) ** Description: Get the list of available PLMNs ** ** ** ** Inputs: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: plist: Pointer to the list of available PLMNs ** ** Return: The size of the list in bytes ** ** Others: None ** ** ** ***************************************************************************/ -int emm_main_get_plmn_list(const char **plist) +int emm_main_get_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, const char **plist) { LOG_FUNC_IN; - int size = IdleMode_update_plmn_list(0); - *plist = _emm_data.plist.buffer; + int size = IdleMode_update_plmn_list(emm_plmn_list, emm_data, 0); + *plist = emm_data->plist.buffer; LOG_FUNC_RETURN (size); } @@ -664,7 +683,6 @@ int emm_main_get_plmn_list(const char **plist) ** ** ** Inputs: format: The requested format of the string repre- ** ** sentation of the PLMN identifier ** - ** Others: _emm_data ** ** ** ** Outputs: plmn: The selected PLMN identifier coded in the ** ** requested format ** @@ -673,7 +691,7 @@ int emm_main_get_plmn_list(const char **plist) ** Others: None ** ** ** ***************************************************************************/ -const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format) +const char *emm_main_get_selected_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format) { LOG_FUNC_IN; @@ -681,10 +699,10 @@ const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format) /* * Get the identifier of the selected PLMN in the list of available PLMNs */ - int index = IdleMode_get_splmn_index(); + int index = IdleMode_get_splmn_index(emm_plmn_list); if ( !(index < 0) ) { - const char *name = _emm_main_get_plmn(&_emm_data.splmn, index, + const char *name = _emm_main_get_plmn(emm_plmn_list, &emm_data->splmn, index, format, &size); if (size > 0) { @@ -703,7 +721,6 @@ const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format) ** ** ** Inputs: format: The requested format of the string repre- ** ** sentation of the PLMN identifier ** - ** Others: _emm_data ** ** ** ** Outputs: plmn: The registered PLMN identifier coded in ** ** the requested format ** @@ -712,7 +729,7 @@ const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format) ** Others: None ** ** ** ***************************************************************************/ -const char *emm_main_get_registered_plmn(network_plmn_t *plmn, int format) +const char *emm_main_get_registered_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format) { LOG_FUNC_IN; @@ -721,10 +738,10 @@ const char *emm_main_get_registered_plmn(network_plmn_t *plmn, int format) /* * Get the identifier of the registered PLMN in the list of available PLMNs */ - int index = IdleMode_get_rplmn_index(); + int index = IdleMode_get_rplmn_index(emm_plmn_list); if ( !(index < 0) ) { - const char *name = _emm_main_get_plmn(&_emm_data.nvdata.rplmn, + const char *name = _emm_main_get_plmn(emm_plmn_list, &emm_data->nvdata.rplmn, index, format, &size); if (size > 0) { @@ -744,17 +761,16 @@ const char *emm_main_get_registered_plmn(network_plmn_t *plmn, int format) ** registration of the UE ** ** ** ** Inputs: None ** - ** Others: _emm_data ** ** ** ** Outputs: None ** ** Return: The current network registration status ** ** Others: None ** ** ** ***************************************************************************/ -Stat_t emm_main_get_plmn_status(void) +Stat_t emm_main_get_plmn_status(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.stat); + LOG_FUNC_RETURN (emm_data->stat); } /**************************************************************************** @@ -765,17 +781,16 @@ Stat_t emm_main_get_plmn_status(void) ** belongs to ** ** ** ** Inputs: None ** - ** Others: _emm_data ** ** ** ** Outputs: None ** ** Return: The Location/Tracking area code ** ** Others: None ** ** ** ***************************************************************************/ -tac_t emm_main_get_plmn_tac(void) +tac_t emm_main_get_plmn_tac(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.tac); + LOG_FUNC_RETURN (emm_data->tac); } /**************************************************************************** @@ -785,17 +800,16 @@ tac_t emm_main_get_plmn_tac(void) ** Description: Get the identifier of the serving cell ** ** ** ** Inputs: None ** - ** Others: _emm_data ** ** ** ** Outputs: None ** ** Return: The serving cell identifier ** ** Others: None ** ** ** ***************************************************************************/ -ci_t emm_main_get_plmn_ci(void) +ci_t emm_main_get_plmn_ci(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.ci); + LOG_FUNC_RETURN (emm_data->ci); } /**************************************************************************** @@ -806,7 +820,6 @@ ci_t emm_main_get_plmn_ci(void) ** ving cell ** ** ** ** Inputs: None ** - ** Others: _emm_data ** ** ** ** Outputs: None ** ** Return: The value of the Radio Access Technology ** @@ -814,10 +827,10 @@ ci_t emm_main_get_plmn_ci(void) ** Others: None ** ** ** ***************************************************************************/ -AcT_t emm_main_get_plmn_rat(void) +AcT_t emm_main_get_plmn_rat(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.rat); + LOG_FUNC_RETURN (emm_data->rat); } /**************************************************************************** @@ -828,7 +841,7 @@ AcT_t emm_main_get_plmn_rat(void) ** network for EPS services or emergency service only ** ** ** ** Inputs: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: TRUE if the UE is currently attached to ** @@ -836,10 +849,10 @@ AcT_t emm_main_get_plmn_rat(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_main_is_attached(void) +int emm_main_is_attached(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.is_attached); + LOG_FUNC_RETURN (emm_data->is_attached); } /**************************************************************************** @@ -850,7 +863,7 @@ int emm_main_is_attached(void) ** network for emergency bearer services ** ** ** ** Inputs: None ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: TRUE if the UE is currently attached or is ** @@ -859,10 +872,10 @@ int emm_main_is_attached(void) ** Others: None ** ** ** ***************************************************************************/ -int emm_main_is_emergency(void) +int emm_main_is_emergency(emm_data_t *emm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_emm_data.is_attached && _emm_data.is_emergency); + LOG_FUNC_RETURN (emm_data->is_attached && emm_data->is_emergency); } /****************************************************************************/ @@ -881,21 +894,21 @@ int emm_main_is_emergency(void) ** present in the network. The list has to be ** ** displayed to the user application when ** ** size > 0. ** - ** Others: _emm_data ** + ** Others: user->emm_data-> ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ -static int _emm_main_callback(int size) +static int _emm_main_callback(user_api_id_t *user_api_id, emm_data_t *emm_data, int size) { LOG_FUNC_IN; /* Forward the notification to the user API */ - int rc = (*_emm_main_user_callback)(_emm_data.stat, _emm_data.tac, - _emm_data.ci, _emm_data.rat, - _emm_data.plist.buffer, size); + int rc = (*_emm_main_user_callback)(user_api_id, emm_data->stat, emm_data->tac, + emm_data->ci, emm_data->rat, + emm_data->plist.buffer, size); LOG_FUNC_RETURN (rc); } @@ -995,24 +1008,24 @@ static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2) ** Others: None ** ** ** ***************************************************************************/ -static const char *_emm_main_get_plmn(const plmn_t *plmn, int index, +static const char *_emm_main_get_plmn(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, int format, size_t *size) { if ( PLMN_IS_VALID(*plmn) ) { switch (format) { case NET_FORMAT_LONG: /* Get the long alpha-numeric representation of the PLMN */ - return IdleMode_get_plmn_fullname(plmn, index, size); + return IdleMode_get_plmn_fullname(emm_plmn_list, plmn, index, size); break; case NET_FORMAT_SHORT: /* Get the short alpha-numeric representation of the PLMN */ - return IdleMode_get_plmn_shortname(plmn, index, size); + return IdleMode_get_plmn_shortname(emm_plmn_list, plmn, index, size); break; case NET_FORMAT_NUM: /* Get the numeric representation of the PLMN */ - return IdleMode_get_plmn_id(plmn, index, size); + return IdleMode_get_plmn_id(emm_plmn_list, plmn, index, size); break; default: @@ -1045,24 +1058,24 @@ static const char *_emm_main_get_plmn(const plmn_t *plmn, int index, ** Others: None ** ** ** ***************************************************************************/ -static int _emm_main_get_plmn_index(const char *plmn, int format) +static int _emm_main_get_plmn_index(emm_plmn_list_t *emm_plmn_list, const char *plmn, int format) { int index = -1; switch (format) { case NET_FORMAT_LONG: /* Get the index of the long alpha-numeric PLMN identifier */ - index = IdleMode_get_plmn_fullname_index(plmn); + index = IdleMode_get_plmn_fullname_index(emm_plmn_list, plmn); break; case NET_FORMAT_SHORT: /* Get the index of the short alpha-numeric PLMN identifier */ - index = IdleMode_get_plmn_shortname_index(plmn); + index = IdleMode_get_plmn_shortname_index(emm_plmn_list, plmn); break; case NET_FORMAT_NUM: /* Get the index of the numeric PLMN identifier */ - index = IdleMode_get_plmn_id_index(plmn); + index = IdleMode_get_plmn_id_index(emm_plmn_list, plmn); break; default: diff --git a/openair3/NAS/UE/EMM/emm_main.h b/openair3/NAS/UE/EMM/emm_main.h index 1ce584210e5c4183e50653b2ac9b527556f16bbd..aa98965b041245bb818efa4a1a5a3be93f972fd4 100644 --- a/openair3/NAS/UE/EMM/emm_main.h +++ b/openair3/NAS/UE/EMM/emm_main.h @@ -41,6 +41,7 @@ Description Defines the EPS Mobility Management procedure call manager, #include "commonDef.h" #include "networkDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -50,6 +51,15 @@ Description Defines the EPS Mobility Management procedure call manager, /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ +/* + * User notification callback, executed whenever a change of data with + * respect of network information (e.g. network registration and/or + * location change, new PLMN becomes available) is notified by the + * EPS Mobility Management sublayer + */ +typedef int (*emm_indication_callback_t) (user_api_id_t *user_api_id, Stat_t, tac_t, ci_t, AcT_t, + const char*, size_t); + /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ @@ -58,34 +68,34 @@ Description Defines the EPS Mobility Management procedure call manager, /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void emm_main_initialize(emm_indication_callback_t cb, const char *imei); +void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const char *imei); -void emm_main_cleanup(void); +void emm_main_cleanup(nas_user_t *user); /* User's getter of UE's identity */ -const imsi_t *emm_main_get_imsi(void); +const imsi_t *emm_main_get_imsi(emm_data_t *emm_data); /* User's getter of the subscriber dialing number */ -const msisdn_t *emm_main_get_msisdn(void); +const msisdn_t *emm_main_get_msisdn(nas_user_t *user); /* User's getter/setter for network selection */ -int emm_main_set_plmn_selection_mode(int mode, int format, +int emm_main_set_plmn_selection_mode(nas_user_t *user, int mode, int format, const network_plmn_t *plmn, int rat); -int emm_main_get_plmn_selection_mode(void); -int emm_main_get_plmn_list(const char **plist); -const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format); +int emm_main_get_plmn_selection_mode(emm_data_t *emm_data); +int emm_main_get_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, const char **plist); +const char *emm_main_get_selected_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format); /* User's getter for network registration */ -Stat_t emm_main_get_plmn_status(void); -tac_t emm_main_get_plmn_tac(void); -ci_t emm_main_get_plmn_ci(void); -AcT_t emm_main_get_plmn_rat(void); -const char *emm_main_get_registered_plmn(network_plmn_t *plmn, int format); +Stat_t emm_main_get_plmn_status(emm_data_t *emm_data); +tac_t emm_main_get_plmn_tac(emm_data_t *emm_data); +ci_t emm_main_get_plmn_ci(emm_data_t *emm_data); +AcT_t emm_main_get_plmn_rat(emm_data_t *emm_data); +const char *emm_main_get_registered_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format); /* User's getter for network attachment */ -int emm_main_is_attached(void); -int emm_main_is_emergency(void); +int emm_main_is_attached(emm_data_t *emm_data); +int emm_main_is_emergency(emm_data_t *emm_data); #endif /* __EMM_MAIN_H__*/ diff --git a/openair3/NAS/UE/EMM/emm_proc.h b/openair3/NAS/UE/EMM/emm_proc.h index 60f71f11c200ebd67ef02b90b5088cfa92dbaead..45052573352c3402fb8f2dcb2e0e9a162f75fa6b 100644 --- a/openair3/NAS/UE/EMM/emm_proc.h +++ b/openair3/NAS/UE/EMM/emm_proc.h @@ -42,38 +42,12 @@ Description Defines the EPS Mobility Management procedures executed at #include "commonDef.h" #include "OctetString.h" #include "LowerLayer.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ -/* Type of network attachment */ -typedef enum { - EMM_ATTACH_TYPE_EPS = 0, - EMM_ATTACH_TYPE_IMSI, - EMM_ATTACH_TYPE_EMERGENCY, - EMM_ATTACH_TYPE_RESERVED, -} emm_proc_attach_type_t; - -/* Type of network detach */ -typedef enum { - EMM_DETACH_TYPE_EPS = 0, - EMM_DETACH_TYPE_IMSI, - EMM_DETACH_TYPE_EPS_IMSI, - EMM_DETACH_TYPE_REATTACH, - EMM_DETACH_TYPE_NOT_REATTACH, - EMM_DETACH_TYPE_RESERVED, -} emm_proc_detach_type_t; - -/* Type of requested identity */ -typedef enum { - EMM_IDENT_TYPE_NOT_AVAILABLE = 0, - EMM_IDENT_TYPE_IMSI, - EMM_IDENT_TYPE_IMEI, - EMM_IDENT_TYPE_IMEISV, - EMM_IDENT_TYPE_TMSI -} emm_proc_identity_type_t; - /****************************************************************************/ /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ @@ -92,48 +66,35 @@ typedef enum { *--------------------------------------------------------------------------- */ int emm_proc_status_ind(unsigned int ueid, int emm_cause); -int emm_proc_status(unsigned int ueid, int emm_cause); - -/* - *--------------------------------------------------------------------------- - * Lower layer procedure - *--------------------------------------------------------------------------- - */ -int emm_proc_lowerlayer_initialize(lowerlayer_success_callback_t success, - lowerlayer_failure_callback_t failure, - lowerlayer_release_callback_t release, - void *args); -int emm_proc_lowerlayer_success(void); -int emm_proc_lowerlayer_failure(int is_initial); -int emm_proc_lowerlayer_release(void); +int emm_proc_status(nas_user_t *user, int emm_cause); /* *--------------------------------------------------------------------------- * UE's Idle mode procedure *--------------------------------------------------------------------------- */ -int emm_proc_initialize(void); -int emm_proc_plmn_selection(int index); -int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat); +int emm_proc_initialize(nas_user_t *user); +int emm_proc_plmn_selection(nas_user_t *user, int index); +int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t rat); /* * -------------------------------------------------------------------------- * Attach procedure * -------------------------------------------------------------------------- */ -int emm_proc_attach(emm_proc_attach_type_t type); +int emm_proc_attach(nas_user_t *user, emm_proc_attach_type_t type); int emm_proc_attach_request(void *args); -int emm_proc_attach_accept(long T3412, long T3402, long T3423, int n_tais, +int emm_proc_attach_accept(nas_user_t *user, long T3412, long T3402, long T3423, int n_tais, tai_t *tai, GUTI_t *guti, int n_eplmns, plmn_t *eplmn, const OctetString *esm_msg); -int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg); +int emm_proc_attach_reject(nas_user_t *user, int emm_cause, const OctetString *esm_msg); int emm_proc_attach_complete(void *args); int emm_proc_attach_failure(int is_initial, void *args); int emm_proc_attach_release(void *args); -int emm_proc_attach_restart(void); +int emm_proc_attach_restart(nas_user_t *user); -int emm_proc_attach_set_emergency(void); -int emm_proc_attach_set_detach(void); +int emm_proc_attach_set_emergency(emm_data_t *emm_data); +int emm_proc_attach_set_detach(void *user); @@ -142,9 +103,9 @@ int emm_proc_attach_set_detach(void); * Detach procedure * -------------------------------------------------------------------------- */ -int emm_proc_detach(emm_proc_detach_type_t type, int switch_off); +int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, int switch_off); int emm_proc_detach_request(void *args); -int emm_proc_detach_accept(void); +int emm_proc_detach_accept(void *args); int emm_proc_detach_failure(int is_initial, void *args); int emm_proc_detach_release(void *args); @@ -154,7 +115,7 @@ int emm_proc_detach_release(void *args); * Identification procedure * -------------------------------------------------------------------------- */ -int emm_proc_identification_request(emm_proc_identity_type_t type); +int emm_proc_identification_request(nas_user_t *user, emm_proc_identity_type_t type); /* @@ -162,10 +123,10 @@ int emm_proc_identification_request(emm_proc_identity_type_t type); * Authentication procedure * -------------------------------------------------------------------------- */ -int emm_proc_authentication_request(int native_ksi, int ksi, +int emm_proc_authentication_request(nas_user_t *user, int native_ksi, int ksi, const OctetString *rand, const OctetString *autn); -int emm_proc_authentication_reject(void); -int emm_proc_authentication_delete(void); +int emm_proc_authentication_reject(nas_user_t *user); +int emm_proc_authentication_delete(nas_user_t *user); /* @@ -173,16 +134,16 @@ int emm_proc_authentication_delete(void); * Security mode control procedure * -------------------------------------------------------------------------- */ -int emm_proc_security_mode_command(int native_ksi, int ksi, int seea, int seia, - int reea, int reia,int imeisv_request); +int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, int seea, int seia, + int reea, int reia, int imeisv_request); /* *--------------------------------------------------------------------------- * Network indication handlers *--------------------------------------------------------------------------- */ -int emm_proc_registration_notify(Stat_t status); -int emm_proc_location_notify(tac_t tac, ci_t ci, AcT_t rat); -int emm_proc_network_notify(int index); +int emm_proc_registration_notify(user_api_id_t *user_api_id, emm_data_t *emm_data, Stat_t status); +int emm_proc_location_notify(user_api_id_t *user_api_id, emm_data_t *emm_data, tac_t tac, ci_t ci, AcT_t rat); +int emm_proc_network_notify(emm_plmn_list_t *emm_plmn_list, user_api_id_t *user_api_id, emm_data_t *emm_data, int index); #endif /* __EMM_PROC_H__*/ diff --git a/openair3/NAS/UE/EMM/emm_proc_defs.h b/openair3/NAS/UE/EMM/emm_proc_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..3779626ac0c384bc3c6fa997d6d12aaaf1be0e60 --- /dev/null +++ b/openair3/NAS/UE/EMM/emm_proc_defs.h @@ -0,0 +1,31 @@ +#ifndef _EMM_PROC_DEFS_H +#define _EMM_PROC_DEFS_H + +/* Type of network attachment */ +typedef enum { + EMM_ATTACH_TYPE_EPS = 0, + EMM_ATTACH_TYPE_IMSI, + EMM_ATTACH_TYPE_EMERGENCY, + EMM_ATTACH_TYPE_RESERVED, +} emm_proc_attach_type_t; + +/* Type of network detach */ +typedef enum { + EMM_DETACH_TYPE_EPS = 0, + EMM_DETACH_TYPE_IMSI, + EMM_DETACH_TYPE_EPS_IMSI, + EMM_DETACH_TYPE_REATTACH, + EMM_DETACH_TYPE_NOT_REATTACH, + EMM_DETACH_TYPE_RESERVED, +} emm_proc_detach_type_t; + +/* Type of requested identity */ +typedef enum { + EMM_IDENT_TYPE_NOT_AVAILABLE = 0, + EMM_IDENT_TYPE_IMSI, + EMM_IDENT_TYPE_IMEI, + EMM_IDENT_TYPE_IMEISV, + EMM_IDENT_TYPE_TMSI +} emm_proc_identity_type_t; + +#endif diff --git a/openair3/NAS/UE/EMM/emm_timers.h b/openair3/NAS/UE/EMM/emm_timers.h new file mode 100644 index 0000000000000000000000000000000000000000..abf7c9ff87411aa362e1e4141af4adeab4d0fbd8 --- /dev/null +++ b/openair3/NAS/UE/EMM/emm_timers.h @@ -0,0 +1,14 @@ +#ifndef EMM_TIMERS_H +#define EMM_TIMERS_H + +/* + * Retransmission timer handlers + */ + +void *emm_attach_t3410_handler(void *); +void *emm_service_t3417_handler(void *); +void *emm_detach_t3421_handler(void *); +void *emm_tau_t3430_handler(void *); + + +#endif diff --git a/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c b/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c index 21e54fd2d033371dfe99d76bea4b8825a85ffd7a..e2133563324f60c61df629acfeb0304d7211e6f1 100644 --- a/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c +++ b/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c @@ -104,20 +104,20 @@ Description Defines the dedicated EPS bearer context activation ESM ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, +int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int default_ebi, const esm_proc_qos_t *qos, const esm_proc_tft_t *tft, int *esm_cause) { LOG_FUNC_IN; - + esm_data_t *esm_data = user->esm_data; int rc = RETURNerror; LOG_TRACE(INFO, "ESM-PROC - Dedicated EPS bearer context activation " "requested by the network (ebi=%d)", ebi); /* Get the PDN connection the dedicated EPS bearer is linked to */ - int pid = esm_ebr_context_get_pid(default_ebi); + int pid = esm_ebr_context_get_pid(esm_data, default_ebi); if (pid < 0) { /* 3GPP TS 24.301, section 6.4.2.5, abnormal case c @@ -131,7 +131,7 @@ int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, } /* Assign dedicated EPS bearer context */ - int new_ebi = esm_ebr_assign(ebi, pid+1, FALSE); + int new_ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, FALSE); if (new_ebi == ESM_EBI_UNASSIGNED) { /* 3GPP TS 24.301, section 6.4.2.5, abnormal cases a and b @@ -141,7 +141,7 @@ int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, int old_pid, old_bid; /* Locally deactivate the existing EPS bearer context and proceed * with the requested dedicated EPS bearer context activation */ - rc = esm_proc_eps_bearer_context_deactivate(TRUE, ebi, + rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, ebi, &old_pid, &old_bid); if (rc != RETURNok) { @@ -149,13 +149,13 @@ int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; } else { /* Assign new dedicated EPS bearer context */ - ebi = esm_ebr_assign(ebi, pid+1, FALSE); + ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, FALSE); } } if (ebi != ESM_EBI_UNASSIGNED) { /* Check syntactical errors in packet filters */ - rc = esm_ebr_context_check_tft(pid, ebi, tft, + rc = esm_ebr_context_check_tft(esm_data, pid, ebi, tft, ESM_EBR_CONTEXT_TFT_CREATE); if (rc != RETURNok) { @@ -165,7 +165,7 @@ int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, *esm_cause = ESM_CAUSE_SYNTACTICAL_ERROR_IN_PACKET_FILTER; } else { /* Create new dedicated EPS bearer context */ - default_ebi = esm_ebr_context_create(pid, ebi, FALSE, qos, tft); + default_ebi = esm_ebr_context_create(esm_data, user->ueid, pid, ebi, FALSE, qos, tft); if (default_ebi != ESM_EBI_UNASSIGNED) { /* Dedicated EPS bearer contextx successfully created */ @@ -206,12 +206,14 @@ int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_dedicated_eps_bearer_context_accept(int is_standalone, int ebi, +int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered) { LOG_FUNC_IN; int rc; + esm_ebr_data_t *esm_ebr_data = user->esm_ebr_data; + user_api_id_t *user_api_id = user->user_api_id; LOG_TRACE(INFO,"ESM-PROC - Dedicated EPS bearer context activation " "accepted by the UE (ebi=%d)", ebi); @@ -222,14 +224,14 @@ int esm_proc_dedicated_eps_bearer_context_accept(int is_standalone, int ebi, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = msg->length; emm_esm->msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Set the EPS bearer context state to ACTIVE */ - rc = esm_ebr_set_status(ebi, ESM_EBR_ACTIVE, ue_triggered); + rc = esm_ebr_set_status(user_api_id, esm_ebr_data, ebi, ESM_EBR_ACTIVE, ue_triggered); if (rc != RETURNok) { /* The EPS bearer context was already in ACTIVE state */ @@ -266,7 +268,7 @@ int esm_proc_dedicated_eps_bearer_context_accept(int is_standalone, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_dedicated_eps_bearer_context_reject(int is_standalone, int ebi, +int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered) { LOG_FUNC_IN; @@ -276,9 +278,9 @@ int esm_proc_dedicated_eps_bearer_context_reject(int is_standalone, int ebi, LOG_TRACE(WARNING, "ESM-PROC - Dedicated EPS bearer context activation " "not accepted by the UE (ebi=%d)", ebi); - if ( !esm_ebr_is_not_in_use(ebi) ) { + if ( !esm_ebr_is_not_in_use(user->esm_ebr_data, ebi) ) { /* Release EPS bearer data currently in use */ - rc = esm_ebr_release(ebi); + rc = esm_ebr_release(user->esm_ebr_data, ebi); } if (rc != RETURNok) { @@ -290,10 +292,10 @@ int esm_proc_dedicated_eps_bearer_context_reject(int is_standalone, int ebi, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = msg->length; emm_esm->msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN (rc); diff --git a/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c b/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c index 82c4e51be8ea82b88d99ac61b536901b0976d12f..a438d65ddb28cac1c76f1240a236f5e163b36e46 100644 --- a/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c +++ b/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c @@ -63,19 +63,6 @@ Description Defines the default EPS bearer context activation ESM /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ -/* - * -------------------------------------------------------------------------- - * Internal data handled by the default EPS bearer context activation - * procedure in the UE - * -------------------------------------------------------------------------- - */ -static struct { - int ebi; /* EPS bearer identity of the default EPS bearer associated - * to the PDN connection to be activated */ -} _default_eps_bearer_context_data = {ESM_EBI_UNASSIGNED}; - - - /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ @@ -101,22 +88,22 @@ static struct { ** Outputs: esm_cause: Cause code returned upon ESM procedure ** ** failure ** ** Return: RETURNok, RETURNerror ** - ** Others: _default_eps_bearer_context_data ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_request(int pid, int ebi, +int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int ebi, const esm_proc_qos_t *qos, int *esm_cause) { LOG_FUNC_IN; - + esm_data_t *esm_data = user->esm_data; + default_eps_bearer_context_data_t *default_eps_bearer_context_data = user->default_eps_bearer_context_data; int rc = RETURNerror; LOG_TRACE(INFO, "ESM-PROC - Default EPS bearer context activation " "requested by the network (ebi=%d)", ebi); /* Assign default EPS bearer context */ - int new_ebi = esm_ebr_assign(ebi, pid+1, TRUE); + int new_ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, TRUE); if (new_ebi == ESM_EBI_UNASSIGNED) { /* 3GPP TS 24.301, section 6.4.1.5, abnormal cases a and b @@ -126,7 +113,7 @@ int esm_proc_default_eps_bearer_context_request(int pid, int ebi, int old_pid, old_bid; /* Locally deactivate the existing EPS bearer context and proceed * with the requested default EPS bearer context activation */ - rc = esm_proc_eps_bearer_context_deactivate(TRUE, ebi, + rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, ebi, &old_pid, &old_bid); if (rc != RETURNok) { @@ -134,17 +121,17 @@ int esm_proc_default_eps_bearer_context_request(int pid, int ebi, *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; } else { /* Assign new default EPS bearer context */ - ebi = esm_ebr_assign(ebi, pid+1, TRUE); + ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, TRUE); } } if (ebi != ESM_EBI_UNASSIGNED) { /* Create new default EPS bearer context */ - ebi = esm_ebr_context_create(pid, ebi, TRUE, qos, NULL); + ebi = esm_ebr_context_create(esm_data, user->ueid, pid, ebi, TRUE, qos, NULL); if (ebi != ESM_EBI_UNASSIGNED) { /* Default EPS bearer contextx successfully created */ - _default_eps_bearer_context_data.ebi = ebi; + default_eps_bearer_context_data->ebi = ebi; rc = RETURNok; } else { /* No resource available */ @@ -188,12 +175,14 @@ int esm_proc_default_eps_bearer_context_request(int pid, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_accept(int is_standalone, int ebi, +int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered) { LOG_FUNC_IN; int rc = RETURNok; + esm_ebr_data_t *esm_ebr_data = user->esm_ebr_data; + user_api_id_t *user_api_id = user->user_api_id; LOG_TRACE(INFO,"ESM-PROC - Default EPS bearer context activation " "accepted by the UE (ebi=%d)", ebi); @@ -205,15 +194,15 @@ int esm_proc_default_eps_bearer_context_accept(int is_standalone, int ebi, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = msg->length; emm_esm->msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } if (rc != RETURNerror) { /* Set the EPS bearer context state to ACTIVE */ - rc = esm_ebr_set_status(ebi, ESM_EBR_ACTIVE, ue_triggered); + rc = esm_ebr_set_status(user_api_id, esm_ebr_data, ebi, ESM_EBR_ACTIVE, ue_triggered); if (rc != RETURNok) { /* The EPS bearer context was already in ACTIVE state */ @@ -256,7 +245,7 @@ int esm_proc_default_eps_bearer_context_accept(int is_standalone, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi, +int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered) { LOG_FUNC_IN; @@ -266,9 +255,9 @@ int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi, LOG_TRACE(WARNING, "ESM-PROC - Default EPS bearer context activation " "not accepted by the UE (ebi=%d)", ebi); - if ( !esm_ebr_is_not_in_use(ebi) ) { + if ( !esm_ebr_is_not_in_use(user->esm_ebr_data, ebi) ) { /* Release EPS bearer data currently in use */ - rc = esm_ebr_release(ebi); + rc = esm_ebr_release(user->esm_ebr_data, ebi); } if (rc != RETURNok) { @@ -280,10 +269,10 @@ int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = msg->length; emm_esm->msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } else { /* An error is returned to notify EMM that the default EPS bearer * activation procedure initiated as part of the initial attach @@ -310,10 +299,9 @@ int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi, ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _default_eps_bearer_context_data ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_complete(void) +int esm_proc_default_eps_bearer_context_complete(default_eps_bearer_context_data_t *default_eps_bearer_context_data) { LOG_FUNC_IN; @@ -321,7 +309,7 @@ int esm_proc_default_eps_bearer_context_complete(void) "ESM-PROC - Default EPS bearer context activation complete"); /* Reset default EPS bearer context internal data */ - _default_eps_bearer_context_data.ebi = ESM_EBI_UNASSIGNED; + default_eps_bearer_context_data->ebi = ESM_EBI_UNASSIGNED; LOG_FUNC_RETURN (RETURNok); } @@ -339,40 +327,29 @@ int esm_proc_default_eps_bearer_context_complete(void) ** ACCEPT message was sent. ** ** ** ** Inputs: None ** - ** Others: _default_eps_bearer_context_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _default_eps_bearer_context_data ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_failure(void) +int esm_proc_default_eps_bearer_context_failure(nas_user_t *user) { LOG_FUNC_IN; + default_eps_bearer_context_data_t *default_eps_bearer_context_data = user->default_eps_bearer_context_data; - int ebi = _default_eps_bearer_context_data.ebi; + int ebi = default_eps_bearer_context_data->ebi; int pid, bid; LOG_TRACE(WARNING, "ESM-PROC - Default EPS bearer context activation failure"); /* Release the default EPS bearer context and enter state INACTIVE */ - int rc = esm_proc_eps_bearer_context_deactivate(TRUE, ebi, &pid, &bid); + int rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, ebi, &pid, &bid); if (rc != RETURNerror) { /* Reset default EPS bearer context internal data */ - _default_eps_bearer_context_data.ebi = ESM_EBI_UNASSIGNED; + default_eps_bearer_context_data->ebi = ESM_EBI_UNASSIGNED; } LOG_FUNC_RETURN (rc); } - -/****************************************************************************/ -/********************* L O C A L F U N C T I O N S *********************/ -/****************************************************************************/ - -/* - * -------------------------------------------------------------------------- - * Timer handlers - * -------------------------------------------------------------------------- - */ diff --git a/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c b/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c index 774c80e97fe453b018e17166801f000e33491083..6ba5e6e1cc2233f16faba458817d6d7ef477ac05 100644 --- a/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c +++ b/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c @@ -74,7 +74,7 @@ Description Defines the EPS bearer context deactivation ESM procedure * in the UE * -------------------------------------------------------------------------- */ -static int _eps_bearer_release(int ebi, int *pid, int *bid); +static int _eps_bearer_release(nas_user_t *user, int ebi, int *pid, int *bid); /****************************************************************************/ @@ -102,7 +102,6 @@ static int _eps_bearer_release(int ebi, int *pid, int *bid); ** gnalling between the UE and the MME ** ** ebi: EPS bearer identity of the EPS bearer con- ** ** text to be deactivated ** - ** Others: _esm_data ** ** ** ** Outputs: pid: Identifier of the PDN connection the EPS ** ** bearer belongs to ** @@ -112,25 +111,25 @@ static int _eps_bearer_release(int ebi, int *pid, int *bid); ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_eps_bearer_context_deactivate(int is_local, int ebi, +int esm_proc_eps_bearer_context_deactivate(nas_user_t *user, int is_local, int ebi, int *pid, int *bid) { LOG_FUNC_IN; int rc = RETURNerror; int i; - + esm_data_t *esm_data = user->esm_data; if (is_local) { if (ebi != ESM_SAP_ALL_EBI) { /* Locally release the EPS bearer context */ - rc = _eps_bearer_release(ebi, pid, bid); + rc = _eps_bearer_release(user, ebi, pid, bid); } else { /* Locally release all the EPS bearer contexts */ *bid = 0; for (*pid = 0; *pid < ESM_DATA_PDN_MAX; (*pid)++) { - if (_esm_data.pdn[*pid].data) { - rc = _eps_bearer_release(ESM_EBI_UNASSIGNED, pid, bid); + if (esm_data->pdn[*pid].data) { + rc = _eps_bearer_release(user, ESM_EBI_UNASSIGNED, pid, bid); if (rc != RETURNok) { break; @@ -146,17 +145,17 @@ int esm_proc_eps_bearer_context_deactivate(int is_local, int ebi, ebi); if (*pid < ESM_DATA_PDN_MAX) { - if (_esm_data.pdn[*pid].pid != *pid) { + if (esm_data->pdn[*pid].pid != *pid) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier %d " "is not valid", *pid); - } else if (_esm_data.pdn[*pid].data == NULL) { + } else if (esm_data->pdn[*pid].data == NULL) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection %d has not been " "allocated", *pid); - } else if (!_esm_data.pdn[*pid].is_active) { + } else if (!esm_data->pdn[*pid].is_active) { LOG_TRACE(WARNING, "ESM-PROC - PDN connection %d is not active", *pid); } else { - esm_pdn_t *pdn = _esm_data.pdn[*pid].data; + esm_pdn_t *pdn = esm_data->pdn[*pid].data; for (i = 0; i < pdn->n_bearers; i++) { if (pdn->bearer[i]->ebi != ebi) { @@ -189,18 +188,19 @@ int esm_proc_eps_bearer_context_deactivate(int is_local, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_eps_bearer_context_deactivate_request(int ebi, int *esm_cause) +int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, int *esm_cause) { LOG_FUNC_IN; int pid, bid; int rc = RETURNok; + esm_data_t *esm_data = user->esm_data; LOG_TRACE(INFO, "ESM-PROC - EPS bearer context deactivation " "requested by the network (ebi=%d)", ebi); /* Release the EPS bearer context entry */ - if (esm_ebr_context_release(ebi, &pid, &bid) == ESM_EBI_UNASSIGNED) { + if (esm_ebr_context_release(user, ebi, &pid, &bid) == ESM_EBI_UNASSIGNED) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release EPS bearer context"); *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; LOG_FUNC_RETURN (RETURNerror); @@ -222,7 +222,7 @@ int esm_proc_eps_bearer_context_deactivate_request(int ebi, int *esm_cause) "connection reactivation"); /* Get PDN context parameters */ - rc = esm_main_get_pdn(pid + 1, &esm_sap.data.pdn_connect.pdn_type, + rc = esm_main_get_pdn(esm_data, pid + 1, &esm_sap.data.pdn_connect.pdn_type, &esm_sap.data.pdn_connect.apn, &esm_sap.data.pdn_connect.is_emergency, &active); @@ -243,7 +243,7 @@ int esm_proc_eps_bearer_context_deactivate_request(int ebi, int *esm_cause) esm_sap.is_standalone = TRUE; esm_sap.data.pdn_connect.is_defined = TRUE; esm_sap.data.pdn_connect.cid = pid + 1; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); } } } @@ -275,12 +275,14 @@ int esm_proc_eps_bearer_context_deactivate_request(int ebi, int *esm_cause) ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_eps_bearer_context_deactivate_accept(int is_standalone, int ebi, +int esm_proc_eps_bearer_context_deactivate_accept(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered) { LOG_FUNC_IN; int rc = RETURNok; + esm_ebr_data_t *esm_ebr_data = user->esm_ebr_data; + user_api_id_t *user_api_id = user->user_api_id; LOG_TRACE(INFO,"ESM-PROC - EPS bearer context deactivation accepted"); @@ -290,15 +292,15 @@ int esm_proc_eps_bearer_context_deactivate_accept(int is_standalone, int ebi, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_sap.u.emm_esm.u.data.msg.length = msg->length; emm_sap.u.emm_esm.u.data.msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } if (rc != RETURNerror) { /* Set the EPS bearer context state to INACTIVE */ - rc = esm_ebr_set_status(ebi, ESM_EBR_INACTIVE, ue_triggered); + rc = esm_ebr_set_status(user_api_id, esm_ebr_data, ebi, ESM_EBR_INACTIVE, ue_triggered); if (rc != RETURNok) { /* The EPS bearer context was already in INACTIVE state */ @@ -309,7 +311,7 @@ int esm_proc_eps_bearer_context_deactivate_accept(int is_standalone, int ebi, } /* Release EPS bearer data */ - rc = esm_ebr_release(ebi); + rc = esm_ebr_release(esm_ebr_data, ebi); } LOG_FUNC_RETURN (rc); @@ -352,27 +354,29 @@ int esm_proc_eps_bearer_context_deactivate_accept(int is_standalone, int ebi, ** Others: None ** ** ** ***************************************************************************/ -static int _eps_bearer_release(int ebi, int *pid, int *bid) +static int _eps_bearer_release(nas_user_t *user, int ebi, int *pid, int *bid) { LOG_FUNC_IN; int rc = RETURNerror; + esm_ebr_data_t *esm_ebr_data = user->esm_ebr_data; + user_api_id_t *user_api_id = user->user_api_id; /* Release the EPS bearer context entry */ - ebi = esm_ebr_context_release(ebi, pid, bid); + ebi = esm_ebr_context_release(user, ebi, pid, bid); if (ebi == ESM_EBI_UNASSIGNED) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release EPS bearer context"); } else { /* Set the EPS bearer context state to INACTIVE */ - rc = esm_ebr_set_status(ebi, ESM_EBR_INACTIVE, FALSE); + rc = esm_ebr_set_status(user_api_id, esm_ebr_data, ebi, ESM_EBR_INACTIVE, FALSE); if (rc != RETURNok) { /* The EPS bearer context was already in INACTIVE state */ LOG_TRACE(WARNING, "ESM-PROC - EBI %d was already INACTIVE", ebi); } else { /* Release EPS bearer data */ - rc = esm_ebr_release(ebi); + rc = esm_ebr_release(esm_ebr_data, ebi); if (rc != RETURNok) { LOG_TRACE(WARNING, diff --git a/openair3/NAS/UE/ESM/EsmStatusHdl.c b/openair3/NAS/UE/ESM/EsmStatusHdl.c index 48e86f4a6062c2ecb12972190f7899a710ab032f..4c8e0aafc1386f089e1a9a0c0f02ebc0df5401aa 100644 --- a/openair3/NAS/UE/ESM/EsmStatusHdl.c +++ b/openair3/NAS/UE/ESM/EsmStatusHdl.c @@ -161,7 +161,7 @@ int esm_proc_status_ind( ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_status(int is_standalone, +int esm_proc_status(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered) { @@ -176,10 +176,10 @@ int esm_proc_status(int is_standalone, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_sap.u.emm_esm.u.data.msg.length = msg->length; emm_sap.u.emm_esm.u.data.msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } diff --git a/openair3/NAS/UE/ESM/PdnConnectivity.c b/openair3/NAS/UE/ESM/PdnConnectivity.c index 2d8718b0a30c6dc0d00c46c453e20307102b3b25..f0a245e83e4036e5e8269fd2550c546e58ce7c57 100644 --- a/openair3/NAS/UE/ESM/PdnConnectivity.c +++ b/openair3/NAS/UE/ESM/PdnConnectivity.c @@ -81,15 +81,15 @@ Description Defines the PDN connectivity ESM procedure executed by the /* * PDN connection handlers */ -static int _pdn_connectivity_create(int pid, const OctetString *apn, +static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetString *apn, esm_proc_pdn_type_t pdn_type, int is_emergency); -static int _pdn_connectivity_update(int pid, const OctetString *apn, +static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetString *apn, esm_proc_pdn_type_t pdn_type, const OctetString *pdn_addr, int esm_cause); -static int _pdn_connectivity_delete(int pid); +static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid); -static int _pdn_connectivity_set_pti(int pid, int pti); -static int _pdn_connectivity_find_apn(const OctetString *apn); -static int _pdn_connectivity_find_pdn(const OctetString *apn, +static int _pdn_connectivity_set_pti(esm_data_t *esm_data, int pid, int pti); +static int _pdn_connectivity_find_apn(esm_data_t *esm_data, const OctetString *apn); +static int _pdn_connectivity_find_pdn(esm_data_t * esm_data, const OctetString *apn, esm_proc_pdn_type_t pdn_type); /* @@ -131,10 +131,9 @@ static void *_pdn_connectivity_t3482_handler(void *); ** the new PDN connection or the released PDN ** ** connection ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity(int cid, int is_to_define, +int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define, esm_proc_pdn_type_t pdn_type, const OctetString *apn, int is_emergency, unsigned int *pti) @@ -143,15 +142,17 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, int rc = RETURNerror; int pid = cid - 1; + esm_data_t *esm_data = user-> esm_data; + esm_pt_data_t *esm_pt_data = user-> esm_pt_data; if (!is_to_define) { LOG_TRACE(INFO, "ESM-PROC - Undefine PDN connection (cid=%d)", cid); /* Delete the PDN connection entry */ - int pti = _pdn_connectivity_delete(pid); + int pti = _pdn_connectivity_delete(esm_data, pid); if (pti != ESM_PT_UNASSIGNED) { /* Release the procedure transaction data */ - rc = esm_pt_release(pti); + rc = esm_pt_release(esm_pt_data, pti); } LOG_FUNC_RETURN(rc); @@ -159,7 +160,7 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, LOG_TRACE(INFO, "ESM-PROC - Assign new procedure transaction identity " "(cid=%d)", cid); /* Assign new procedure transaction identity */ - *pti = esm_pt_assign(); + *pti = esm_pt_assign(esm_pt_data); if (*pti == ESM_PT_UNASSIGNED) { LOG_TRACE(WARNING, "ESM-PROC - Failed to assign new procedure " @@ -168,7 +169,7 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, } /* Update the PDN connection data */ - rc = _pdn_connectivity_set_pti(pid, *pti); + rc = _pdn_connectivity_set_pti(esm_data, pid, *pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to update PDN connection"); @@ -182,14 +183,14 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, (pdn_type == ESM_PDN_TYPE_IPV6)? "IPv6" : "IPv4v6", apn->value, cid); - if (is_emergency && _esm_data.emergency) { + if (is_emergency && esm_data->emergency) { /* The UE shall not request additional PDN connection for * emergency bearer services */ LOG_TRACE(WARNING, "ESM-PROC - PDN connection for emergency bearer " "services is already active"); LOG_FUNC_RETURN (RETURNerror); } else if (pid < ESM_DATA_PDN_MAX) { - if ((pid == _esm_data.pdn[pid].pid) && (_esm_data.pdn[pid].is_active)) { + if ((pid == esm_data->pdn[pid].pid) && (esm_data->pdn[pid].is_active)) { /* PDN connection with the specified identifier is active */ LOG_TRACE(WARNING, "ESM-PROC - PDN connection is active"); LOG_FUNC_RETURN (RETURNerror); @@ -201,15 +202,15 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, if (apn && apn->length > 0) { /* The UE requested subsequent connectivity to additionnal PDNs */ - int pid = _pdn_connectivity_find_apn(apn); + int pid = _pdn_connectivity_find_apn(esm_data, apn); - if ( (pid >= 0) && _esm_data.pdn[pid].is_active ) { + if ( (pid >= 0) && esm_data->pdn[pid].is_active ) { /* An active PDN connection to this APN already exists */ - if ( (_esm_data.pdn[pid].data->type != ESM_PDN_TYPE_IPV4V6) && - (_esm_data.pdn[pid].data->type != pdn_type) ) { + if ( (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4V6) && + (esm_data->pdn[pid].data->type != pdn_type) ) { /* The UE is requesting PDN connection for other IP version * than the one already activated */ - if (!_esm_data.pdn[pid].data->addr_realloc) { + if (!esm_data->pdn[pid].data->addr_realloc) { /* The network does not allow PDN connectivity using * IPv4 and IPv6 address versions to the same APN */ if (pdn_type != ESM_PDN_TYPE_IPV4V6) { @@ -220,7 +221,7 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, } else { LOG_TRACE(WARNING, "ESM-PROC - %s PDN connection to %s " "already exists", - (_esm_data.pdn[pid].data->type != + (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)? "IPv6" : "IPv4", apn->value); } @@ -232,8 +233,8 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, * same IP version than the one already activated */ LOG_TRACE(WARNING, "ESM-PROC - %s PDN connection to %s " "already exists", - (_esm_data.pdn[pid].data->type != ESM_PDN_TYPE_IPV4)? - (_esm_data.pdn[pid].data->type != ESM_PDN_TYPE_IPV6)? + (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)? + (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV6)? "IPv4v6" : "IPv6" : "IPv4", apn->value); LOG_FUNC_RETURN (RETURNerror); } @@ -248,7 +249,7 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, * not already established, or may have been allowed to request PDN * connectivity for other IP version than the one already activated */ - rc = _pdn_connectivity_create(pid, apn, pdn_type, is_emergency); + rc = _pdn_connectivity_create(esm_data, pid, apn, pdn_type, is_emergency); LOG_FUNC_RETURN(rc); } @@ -279,11 +280,11 @@ int esm_proc_pdn_connectivity(int cid, int is_to_define, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity_request(int is_standalone, int pti, +int esm_proc_pdn_connectivity_request(nas_user_t *user, int is_standalone, int pti, OctetString *msg, int sent_by_ue) { LOG_FUNC_IN; - + esm_pt_data_t *esm_pt_data = user->esm_pt_data; int rc = RETURNok; LOG_TRACE(INFO, "ESM-PROC - Initiate PDN connectivity (pti=%d)", pti); @@ -295,21 +296,21 @@ int esm_proc_pdn_connectivity_request(int is_standalone, int pti, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = msg->length; emm_esm->msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Start T3482 retransmission timer */ - rc = esm_pt_start_timer(pti, msg, T3482_DEFAULT_VALUE, + rc = esm_pt_start_timer(user, pti, msg, T3482_DEFAULT_VALUE, _pdn_connectivity_t3482_handler); } } if (rc != RETURNerror) { /* Set the procedure transaction state to PENDING */ - rc = esm_pt_set_status(pti, ESM_PT_PENDING); + rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_PENDING); if (rc != RETURNok) { /* The procedure transaction was already in PENDING state */ @@ -346,15 +347,17 @@ int esm_proc_pdn_connectivity_request(int is_standalone, int pti, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity_accept(int pti, esm_proc_pdn_type_t pdn_type, +int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_type_t pdn_type, const OctetString *pdn_addr, const OctetString *apn, int *esm_cause) { LOG_FUNC_IN; - + esm_data_t *esm_data = user->esm_data; + esm_pt_data_t *esm_pt_data = user->esm_pt_data; int rc; int pid = RETURNerror; char apn_first_char[4]; + char str[128]; if (isprint(apn->value[0])) { apn_first_char[0] = '\0'; @@ -364,14 +367,14 @@ int esm_proc_pdn_connectivity_accept(int pti, esm_proc_pdn_type_t pdn_type, LOG_TRACE(INFO, "ESM-PROC - PDN connectivity accepted by the network " "(pti=%d) APN = %s\"%s\", IP address = %s", pti, apn_first_char, isprint(apn->value[0]) ? &apn->value[0] : &apn->value[1], - (pdn_type == ESM_PDN_TYPE_IPV4)? esm_data_get_ipv4_addr(pdn_addr) : - (pdn_type == ESM_PDN_TYPE_IPV6)? esm_data_get_ipv6_addr(pdn_addr) : - esm_data_get_ipv4v6_addr(pdn_addr)); + (pdn_type == ESM_PDN_TYPE_IPV4)? esm_data_get_ipv4_addr(pdn_addr, str) : + (pdn_type == ESM_PDN_TYPE_IPV6)? esm_data_get_ipv6_addr(pdn_addr, str) : + esm_data_get_ipv4v6_addr(pdn_addr, str)); /* Stop T3482 timer if running */ - (void) esm_pt_stop_timer(pti); + esm_pt_stop_timer(esm_pt_data, pti); /* Set the procedure transaction state to INACTIVE */ - rc = esm_pt_set_status(pti, ESM_PT_INACTIVE); + rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state @@ -391,7 +394,7 @@ int esm_proc_pdn_connectivity_accept(int pti, esm_proc_pdn_type_t pdn_type, */ /* Check whether a PDN connection exists to this APN */ - pid = _pdn_connectivity_find_pdn(apn, pdn_type); + pid = _pdn_connectivity_find_pdn(esm_data, apn, pdn_type); if (pid < 0) { /* No any PDN connection has been defined to establish connectivity @@ -403,7 +406,7 @@ int esm_proc_pdn_connectivity_accept(int pti, esm_proc_pdn_type_t pdn_type, } /* Update the PDN connection */ - rc = _pdn_connectivity_update(pid, apn, pdn_type, pdn_addr, *esm_cause); + rc = _pdn_connectivity_update(esm_data, pid, apn, pdn_type, pdn_addr, *esm_cause); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to update PDN connection " @@ -438,19 +441,19 @@ int esm_proc_pdn_connectivity_accept(int pti, esm_proc_pdn_type_t pdn_type, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity_reject(int pti, int *esm_cause) +int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause) { LOG_FUNC_IN; - + esm_pt_data_t *esm_pt_data = user->esm_pt_data; int rc; LOG_TRACE(WARNING, "ESM-PROC - PDN connectivity rejected by " "the network (pti=%d), ESM cause = %d", pti, *esm_cause); /* Stop T3482 timer if running */ - (void) esm_pt_stop_timer(pti); + (void) esm_pt_stop_timer(esm_pt_data, pti); /* Set the procedure transaction state to INACTIVE */ - rc = esm_pt_set_status(pti, ESM_PT_INACTIVE); + rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state */ @@ -458,7 +461,7 @@ int esm_proc_pdn_connectivity_reject(int pti, int *esm_cause) *esm_cause = ESM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE; } else { /* Release the procedure transaction identity */ - rc = esm_pt_release(pti); + rc = esm_pt_release(user->esm_pt_data, pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); @@ -489,21 +492,21 @@ int esm_proc_pdn_connectivity_reject(int pti, int *esm_cause) ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity_complete(void) +int esm_proc_pdn_connectivity_complete(nas_user_t *user) { LOG_FUNC_IN; - + esm_pt_data_t *esm_pt_data = user->esm_pt_data; int rc = RETURNerror; LOG_TRACE(INFO, "ESM-PROC - PDN connectivity complete"); /* Get the procedure transaction identity assigned to the PDN connection * entry which is still pending in the inactive state */ - int pti = esm_pt_get_pending_pti(ESM_PT_INACTIVE); + int pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_INACTIVE); if (pti != ESM_PT_UNASSIGNED) { /* Release the procedure transaction identity */ - rc = esm_pt_release(pti); + rc = esm_pt_release(esm_pt_data, pti); } LOG_FUNC_RETURN(rc); @@ -530,10 +533,10 @@ int esm_proc_pdn_connectivity_complete(void) ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity_failure(int is_pending) +int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending) { LOG_FUNC_IN; - + esm_pt_data_t *esm_pt_data = user->esm_pt_data; int rc; int pti; @@ -543,7 +546,7 @@ int esm_proc_pdn_connectivity_failure(int is_pending) if (is_pending) { /* Get the procedure transaction identity assigned to the pending PDN * connection entry */ - pti = esm_pt_get_pending_pti(ESM_PT_PENDING); + pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_PENDING); if (pti == ESM_PT_UNASSIGNED) { LOG_TRACE(ERROR, "ESM-PROC - No procedure transaction is PENDING"); @@ -551,15 +554,15 @@ int esm_proc_pdn_connectivity_failure(int is_pending) } /* Set the procedure transaction state to INACTIVE */ - (void) esm_pt_set_status(pti, ESM_PT_INACTIVE); + (void) esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE); } else { /* Get the procedure transaction identity assigned to the PDN * connection entry which is still pending in the inactive state */ - pti = esm_pt_get_pending_pti(ESM_PT_INACTIVE); + pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_INACTIVE); } /* Release the procedure transaction identity */ - rc = esm_pt_release(pti); + rc = esm_pt_release(esm_pt_data, pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); @@ -603,6 +606,7 @@ int esm_proc_pdn_connectivity_failure(int is_pending) ** Others: None ** ** ** ***************************************************************************/ +// FIXME static void *_pdn_connectivity_t3482_handler(void *args) { LOG_FUNC_IN; @@ -610,7 +614,9 @@ static void *_pdn_connectivity_t3482_handler(void *args) int rc; /* Get retransmission timer parameters data */ - esm_pt_timer_data_t *data = (esm_pt_timer_data_t *)(args); + esm_pt_timer_data_t *data = args; + nas_user_t *user = data->user; + esm_pt_data_t *esm_pt_data = user->esm_pt_data; /* Increment the retransmission counter */ data->count += 1; @@ -626,19 +632,19 @@ static void *_pdn_connectivity_t3482_handler(void *args) * has to be sent again */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = data->msg.length; emm_esm->msg.value = data->msg.value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Restart the timer T3482 */ - rc = esm_pt_start_timer(data->pti, &data->msg, T3482_DEFAULT_VALUE, + rc = esm_pt_start_timer(user, data->pti, &data->msg, T3482_DEFAULT_VALUE, _pdn_connectivity_t3482_handler); } } else { /* Set the procedure transaction state to INACTIVE */ - rc = esm_pt_set_status(data->pti, ESM_PT_INACTIVE); + rc = esm_pt_set_status(esm_pt_data, data->pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state */ @@ -646,7 +652,7 @@ static void *_pdn_connectivity_t3482_handler(void *args) data->pti); } else { /* Release the transaction identity assigned to this procedure */ - rc = esm_pt_release(data->pti); + rc = esm_pt_release(esm_pt_data, data->pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", @@ -676,14 +682,12 @@ static void *_pdn_connectivity_t3482_handler(void *args) ** pdn_type: PDN type (IPv4, IPv6, IPv4v6) ** ** is_emergency: TRUE if the PDN connection has to be esta- ** ** blished for emergency bearer services ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -static int _pdn_connectivity_create(int pid, const OctetString *apn, +static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetString *apn, esm_proc_pdn_type_t pdn_type, int is_emergency) { @@ -693,14 +697,14 @@ static int _pdn_connectivity_create(int pid, const OctetString *apn, if (pid >= ESM_DATA_PDN_MAX) { return (RETURNerror); - } else if (_esm_data.pdn[pid].is_active) { + } else if (esm_data->pdn[pid].is_active) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active"); return (RETURNerror); } - if (_esm_data.pdn[pid].data != NULL) { + if (esm_data->pdn[pid].data != NULL) { /* Update existing non-active PDN connection */ - pdn = _esm_data.pdn[pid].data; + pdn = esm_data->pdn[pid].data; } else { /* Create new PDN connection */ pdn = (esm_pdn_t *)malloc(sizeof(esm_pdn_t)); @@ -713,13 +717,13 @@ static int _pdn_connectivity_create(int pid, const OctetString *apn, memset(pdn, 0, sizeof(esm_pdn_t)); /* Increment the number of PDN connections */ - _esm_data.n_pdns += 1; + esm_data->n_pdns += 1; /* Set the PDN connection identifier */ - _esm_data.pdn[pid].pid = pid; + esm_data->pdn[pid].pid = pid; /* Reset the PDN connection active indicator */ - _esm_data.pdn[pid].is_active = FALSE; + esm_data->pdn[pid].is_active = FALSE; /* Setup the PDN connection data */ - _esm_data.pdn[pid].data = pdn; + esm_data->pdn[pid].data = pdn; } /* Update the PDN connection data */ @@ -760,10 +764,9 @@ static int _pdn_connectivity_create(int pid, const OctetString *apn, ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -static int _pdn_connectivity_update(int pid, const OctetString *apn, +static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetString *apn, esm_proc_pdn_type_t pdn_type, const OctetString *pdn_addr, int esm_cause) @@ -772,21 +775,21 @@ static int _pdn_connectivity_update(int pid, const OctetString *apn, if (pid >= ESM_DATA_PDN_MAX) { return (RETURNerror); - } else if (pid != _esm_data.pdn[pid].pid) { + } else if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier is not valid"); return (RETURNerror); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection has not been allocated"); return (RETURNerror); - } else if (_esm_data.pdn[pid].is_active) { + } else if (esm_data->pdn[pid].is_active) { LOG_TRACE(WARNING, "ESM-PROC - Active %s PDN connection to %s already " - "exists", (_esm_data.pdn[pid].data->type != ESM_PDN_TYPE_IPV4)? - "IPv6" : "IPv4", _esm_data.pdn[pid].data->apn.value); + "exists", (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)? + "IPv6" : "IPv4", esm_data->pdn[pid].data->apn.value); return (RETURNerror); } /* Get the PDN connection */ - esm_pdn_t *pdn = _esm_data.pdn[pid].data; + esm_pdn_t *pdn = esm_data->pdn[pid].data; /* Setup the Access Point Name value */ if ( apn && (apn->length > 0) ) { @@ -847,49 +850,47 @@ static int _pdn_connectivity_update(int pid, const OctetString *apn, ** ** ** Inputs: pid: Identifier of the PDN connection to be ** ** released ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The identity of the procedure transaction ** ** assigned to the PDN connection when suc- ** ** cessfully released; ** ** UNASSIGNED value otherwise. ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -static int _pdn_connectivity_delete(int pid) +static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid) { int pti = ESM_PT_UNASSIGNED; if (pid < ESM_DATA_PDN_MAX) { - if (pid != _esm_data.pdn[pid].pid) { + if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier is not valid"); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection has not been allocated"); - } else if (_esm_data.pdn[pid].is_active) { + } else if (esm_data->pdn[pid].is_active) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active"); } else { /* Get the identity of the procedure transaction that created * the PDN connection */ - pti = _esm_data.pdn[pid].data->pti; + pti = esm_data->pdn[pid].data->pti; } } if (pti != ESM_PT_UNASSIGNED) { /* Decrement the number of PDN connections */ - _esm_data.n_pdns -= 1; + esm_data->n_pdns -= 1; /* Set the PDN connection as available */ - _esm_data.pdn[pid].pid = -1; + esm_data->pdn[pid].pid = -1; /* Release allocated PDN connection data */ - if (_esm_data.pdn[pid].data->apn.length > 0) { - free(_esm_data.pdn[pid].data->apn.value); + if (esm_data->pdn[pid].data->apn.length > 0) { + free(esm_data->pdn[pid].data->apn.value); } - free(_esm_data.pdn[pid].data); - _esm_data.pdn[pid].data = NULL; + free(esm_data->pdn[pid].data); + esm_data->pdn[pid].data = NULL; LOG_TRACE(WARNING, "ESM-PROC - PDN connection %d released", pid); } @@ -910,24 +911,23 @@ static int _pdn_connectivity_delete(int pid) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -static int _pdn_connectivity_set_pti(int pid, int pti) +static int _pdn_connectivity_set_pti(esm_data_t *esm_data, int pid, int pti) { if (pid < ESM_DATA_PDN_MAX) { - if (pid != _esm_data.pdn[pid].pid) { + if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier is not valid"); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection has not been allocated"); - } else if (_esm_data.pdn[pid].is_active) { + } else if (esm_data->pdn[pid].is_active) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active"); } else { /* Update the identity of the procedure transaction assigned to * the PDN connection */ - _esm_data.pdn[pid].data->pti = pti; + esm_data->pdn[pid].data->pti = pti; return (RETURNok); } } @@ -943,7 +943,6 @@ static int _pdn_connectivity_set_pti(int pid, int pti) ** for the specified APN ** ** ** ** Inputs: apn: Access Point Name of the PDN connection ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The identifier of the PDN connection if ** @@ -951,17 +950,17 @@ static int _pdn_connectivity_set_pti(int pid, int pti) ** Others: None ** ** ** ***************************************************************************/ -static int _pdn_connectivity_find_apn(const OctetString *apn) +static int _pdn_connectivity_find_apn(esm_data_t *esm_data, const OctetString *apn) { int i; for (i = 0; i < ESM_DATA_PDN_MAX; i++) { - if ( (_esm_data.pdn[i].pid != -1) && _esm_data.pdn[i].data ) { - if (_esm_data.pdn[i].data->apn.length != apn->length) { + if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) { + if (esm_data->pdn[i].data->apn.length != apn->length) { continue; } - if (memcmp(_esm_data.pdn[i].data->apn.value, + if (memcmp(esm_data->pdn[i].data->apn.value, apn->value, apn->length) != 0) { continue; } @@ -972,7 +971,7 @@ static int _pdn_connectivity_find_apn(const OctetString *apn) } /* Return the identifier of the PDN connection */ - return (_esm_data.pdn[i].pid); + return (esm_data->pdn[i].pid); } /**************************************************************************** @@ -984,7 +983,6 @@ static int _pdn_connectivity_find_apn(const OctetString *apn) ** ** ** Inputs: apn: Access Point Name of the PDN connection ** ** pdn_type: PDN address type ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The identifier of the PDN connection if ** @@ -992,38 +990,38 @@ static int _pdn_connectivity_find_apn(const OctetString *apn) ** Others: None ** ** ** ***************************************************************************/ -static int _pdn_connectivity_find_pdn(const OctetString *apn, +static int _pdn_connectivity_find_pdn(esm_data_t *esm_data, const OctetString *apn, const esm_proc_pdn_type_t pdn_type) { int i; for (i = 0; i < ESM_DATA_PDN_MAX; i++) { - if ( (_esm_data.pdn[i].pid != -1) && _esm_data.pdn[i].data ) { + if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) { /* PDN connection established during initial network attachment */ - if (_esm_data.pdn[i].data->apn.length == 0) { + if (esm_data->pdn[i].data->apn.length == 0) { break; } /* Subsequent PDN connection established for the specified APN */ - if (_esm_data.pdn[i].data->apn.length != apn->length) { + if (esm_data->pdn[i].data->apn.length != apn->length) { continue; } - if (memcmp(_esm_data.pdn[i].data->apn.value, + if (memcmp(esm_data->pdn[i].data->apn.value, apn->value, apn->length) != 0) { continue; } - if (_esm_data.pdn[i].data->type == ESM_PDN_TYPE_IPV4V6) { + if (esm_data->pdn[i].data->type == ESM_PDN_TYPE_IPV4V6) { break; } - if (_esm_data.pdn[i].data->type == pdn_type) { + if (esm_data->pdn[i].data->type == pdn_type) { break; } } } /* Return the identifier of the PDN connection */ - return (_esm_data.pdn[i].pid); + return (esm_data->pdn[i].pid); } diff --git a/openair3/NAS/UE/ESM/PdnDisconnect.c b/openair3/NAS/UE/ESM/PdnDisconnect.c index 3cb2f563858ad1306ea241ccf8357874dfb5b571..4b5c0f06e5b0bfe14d7cae3613c3393ea7350e5e 100644 --- a/openair3/NAS/UE/ESM/PdnDisconnect.c +++ b/openair3/NAS/UE/ESM/PdnDisconnect.c @@ -73,7 +73,7 @@ Description Defines the PDN disconnect ESM procedure executed by the /* * PDN disconnection handlers */ -static int _pdn_disconnect_get_default_ebi(int pti); +static int _pdn_disconnect_get_default_ebi(esm_data_t *esm_data, int pti); /* * Timer handlers @@ -104,7 +104,6 @@ static void *_pdn_disconnect_t3492_handler(void *); ** tifier ** ** ** ** Inputs: cid: PDN context identifier ** - ** Others: _esm_data ** ** ** ** Outputs: pti: Procedure transaction identity assigned to ** ** the PDN connection to be released ** @@ -114,7 +113,7 @@ static void *_pdn_disconnect_t3492_handler(void *); ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_disconnect(int cid, unsigned int *pti, unsigned int *ebi) +int esm_proc_pdn_disconnect(esm_data_t *esm_data, int cid, unsigned int *pti, unsigned int *ebi) { LOG_FUNC_IN; @@ -122,21 +121,21 @@ int esm_proc_pdn_disconnect(int cid, unsigned int *pti, unsigned int *ebi) int pid = cid - 1; if (pid < ESM_DATA_PDN_MAX) { - if (pid != _esm_data.pdn[pid].pid) { + if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(WARNING, "ESM-PROC - PDN connection identifier %d is " "not valid", pid); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection %d has not been " "allocated", pid); - } else if (!_esm_data.pdn[pid].is_active) { + } else if (!esm_data->pdn[pid].is_active) { LOG_TRACE(WARNING, "ESM-PROC - PDN connection is not active"); } else { /* Get the procedure transaction identity assigned to the PDN * connection to be released */ - *pti = _esm_data.pdn[pid].data->pti; + *pti = esm_data->pdn[pid].data->pti; /* Get the EPS bearer identity of the default bearer associated * with the PDN to disconnect from */ - *ebi = _esm_data.pdn[pid].data->bearer[0]->ebi; + *ebi = esm_data->pdn[pid].data->bearer[0]->ebi; rc = RETURNok; } } @@ -168,13 +167,13 @@ int esm_proc_pdn_disconnect(int cid, unsigned int *pti, unsigned int *ebi) ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_disconnect_request(int is_standalone, int pti, +int esm_proc_pdn_disconnect_request(nas_user_t *user, int is_standalone, int pti, OctetString *msg, int sent_by_ue) { LOG_FUNC_IN; int rc = RETURNok; - + esm_pt_data_t *esm_pt_data = user->esm_pt_data; LOG_TRACE(INFO, "ESM-PROC - Initiate PDN disconnection (pti=%d)", pti); if (is_standalone) { @@ -184,21 +183,21 @@ int esm_proc_pdn_disconnect_request(int is_standalone, int pti, * Notity EMM that ESM PDU has to be forwarded to lower layers */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = msg->length; emm_esm->msg.value = msg->value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Start T3482 retransmission timer */ - rc = esm_pt_start_timer(pti, msg, T3492_DEFAULT_VALUE, + rc = esm_pt_start_timer(user, pti, msg, T3492_DEFAULT_VALUE, _pdn_disconnect_t3492_handler); } } if (rc != RETURNerror) { /* Set the procedure transaction state to PENDING */ - rc = esm_pt_set_status(pti, ESM_PT_PENDING); + rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_PENDING); if (rc != RETURNok) { /* The procedure transaction was already in PENDING state */ @@ -232,7 +231,7 @@ int esm_proc_pdn_disconnect_request(int is_standalone, int pti, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_disconnect_accept(int pti, int *esm_cause) +int esm_proc_pdn_disconnect_accept(esm_pt_data_t *esm_pt_data, int pti, int *esm_cause) { LOG_FUNC_IN; @@ -240,9 +239,9 @@ int esm_proc_pdn_disconnect_accept(int pti, int *esm_cause) "(pti=%d)", pti); /* Stop T3492 timer if running */ - (void) esm_pt_stop_timer(pti); + (void) esm_pt_stop_timer(esm_pt_data, pti); /* Set the procedure transaction state to INACTIVE */ - int rc = esm_pt_set_status(pti, ESM_PT_INACTIVE); + int rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state */ @@ -251,7 +250,7 @@ int esm_proc_pdn_disconnect_accept(int pti, int *esm_cause) } else { /* Immediately release the transaction identity assigned to this * procedure */ - rc = esm_pt_release(pti); + rc = esm_pt_release(esm_pt_data, pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); @@ -284,19 +283,19 @@ int esm_proc_pdn_disconnect_accept(int pti, int *esm_cause) ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause) +int esm_proc_pdn_disconnect_reject(nas_user_t *user, int pti, int *esm_cause) { LOG_FUNC_IN; - + esm_data_t *esm_data = user->esm_data; int rc; LOG_TRACE(WARNING, "ESM-PROC - PDN disconnection rejected by the network " "(pti=%d), ESM cause = %d", pti, *esm_cause); /* Stop T3492 timer if running */ - (void) esm_pt_stop_timer(pti); + (void) esm_pt_stop_timer(user->esm_pt_data, pti); /* Set the procedure transaction state to INACTIVE */ - rc = esm_pt_set_status(pti, ESM_PT_INACTIVE); + rc = esm_pt_set_status(user->esm_pt_data, pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state @@ -305,7 +304,7 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause) *esm_cause = ESM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE; } else { /* Release the transaction identity assigned to this procedure */ - rc = esm_pt_release(pti); + rc = esm_pt_release(user->esm_pt_data, pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); @@ -313,7 +312,7 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause) } else if (*esm_cause != ESM_CAUSE_LAST_PDN_DISCONNECTION_NOT_ALLOWED) { /* Get the identity of the default EPS bearer context allocated to * the PDN connection entry assigned to this procedure transaction */ - int ebi = _pdn_disconnect_get_default_ebi(pti); + int ebi = _pdn_disconnect_get_default_ebi(esm_data, pti); if (ebi < 0) { LOG_TRACE(ERROR, "ESM-PROC - No default EPS bearer found"); @@ -331,7 +330,7 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause) esm_sap.recv = NULL; esm_sap.send.length = 0; esm_sap.data.eps_bearer_context_deactivate.ebi = ebi; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); if (rc != RETURNok) { *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; @@ -382,7 +381,8 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause) static void *_pdn_disconnect_t3492_handler(void *args) { LOG_FUNC_IN; - + nas_user_t *user = args; + esm_data_t *esm_data = user->esm_data;; int rc; /* Get retransmission timer parameters data */ @@ -402,19 +402,19 @@ static void *_pdn_disconnect_t3492_handler(void *args) * has to be sent again */ emm_sap.primitive = EMMESM_UNITDATA_REQ; - emm_sap.u.emm_esm.ueid = 0; + emm_sap.u.emm_esm.ueid = user->ueid; emm_esm->msg.length = data->msg.length; emm_esm->msg.value = data->msg.value; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { /* Restart the timer T3492 */ - rc = esm_pt_start_timer(data->pti, &data->msg, T3492_DEFAULT_VALUE, + rc = esm_pt_start_timer(user, data->pti, &data->msg, T3492_DEFAULT_VALUE, _pdn_disconnect_t3492_handler); } } else { /* Set the procedure transaction state to INACTIVE */ - rc = esm_pt_set_status(data->pti, ESM_PT_INACTIVE); + rc = esm_pt_set_status(user->esm_pt_data, data->pti, ESM_PT_INACTIVE); if (rc != RETURNok) { /* The procedure transaction was already in INACTIVE state */ @@ -422,7 +422,7 @@ static void *_pdn_disconnect_t3492_handler(void *args) data->pti); } else { /* Release the transaction identity assigned to this procedure */ - rc = esm_pt_release(data->pti); + rc = esm_pt_release(user->esm_pt_data, data->pti); if (rc != RETURNok) { LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", @@ -431,7 +431,7 @@ static void *_pdn_disconnect_t3492_handler(void *args) /* Get the identity of the default EPS bearer context * allocated to the PDN connection entry assigned to * this procedure transaction */ - int ebi = _pdn_disconnect_get_default_ebi(data->pti); + int ebi = _pdn_disconnect_get_default_ebi(esm_data, data->pti); if (ebi < 0) { LOG_TRACE(ERROR, "ESM-PROC - No default EPS bearer found"); @@ -448,7 +448,7 @@ static void *_pdn_disconnect_t3492_handler(void *args) esm_sap.recv = NULL; esm_sap.send.length = 0; esm_sap.data.eps_bearer_context_deactivate.ebi = ebi; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); } } } @@ -471,7 +471,6 @@ static void *_pdn_disconnect_t3492_handler(void *args) ** ven procedure transaction identity has been assigned ** ** ** ** Inputs: pti: The procedure transaction identity ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The EPS bearer identity of the default EPS ** @@ -479,22 +478,22 @@ static void *_pdn_disconnect_t3492_handler(void *args) ** Others: None ** ** ** ***************************************************************************/ -static int _pdn_disconnect_get_default_ebi(int pti) +static int _pdn_disconnect_get_default_ebi(esm_data_t *esm_data, int pti) { int ebi = -1; int i; for (i = 0; i < ESM_DATA_PDN_MAX; i++) { - if ( (_esm_data.pdn[i].pid != -1) && _esm_data.pdn[i].data ) { - if (_esm_data.pdn[i].data->pti != pti) { + if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) { + if (esm_data->pdn[i].data->pti != pti) { continue; } /* PDN entry found */ - if (_esm_data.pdn[i].data->bearer[0] != NULL) { + if (esm_data->pdn[i].data->bearer[0] != NULL) { /* Get the EPS bearer identity of the default EPS bearer * context associated to the PDN connection */ - ebi = _esm_data.pdn[i].data->bearer[0]->ebi; + ebi = esm_data->pdn[i].data->bearer[0]->ebi; } break; diff --git a/openair3/NAS/UE/ESM/SAP/esm_recv.c b/openair3/NAS/UE/ESM/SAP/esm_recv.c index 243d619896732ca14f4635ba00729d9a362186c5..03a421558113c48500f8d5893fcfb21e842970ec 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_recv.c +++ b/openair3/NAS/UE/ESM/SAP/esm_recv.c @@ -74,7 +74,7 @@ Description Defines functions executed at the ESM Service Access ** ** ** Description: Processes ESM status message ** ** ** - ** Inputs: ueid: UE local identifier ** + ** Inputs: ** ** pti: Procedure transaction identity ** ** ebi: EPS bearer identity ** ** msg: The received ESM message ** @@ -135,7 +135,7 @@ int esm_recv_status(int pti, int ebi, const esm_status_msg *msg) ** Others: None ** ** ** ***************************************************************************/ -int esm_recv_pdn_connectivity_reject(int pti, int ebi, +int esm_recv_pdn_connectivity_reject(nas_user_t *user, int pti, int ebi, const pdn_connectivity_reject_msg *msg) { LOG_FUNC_IN; @@ -154,7 +154,7 @@ int esm_recv_pdn_connectivity_reject(int pti, int ebi, */ LOG_TRACE(WARNING, "ESM-SAP - Invalid PTI value (pti=%d)", pti); LOG_FUNC_RETURN (ESM_CAUSE_INVALID_PTI_VALUE); - } else if ( esm_pt_is_not_in_use(pti) ) { + } else if ( esm_pt_is_not_in_use(user->esm_pt_data, pti) ) { /* 3GPP TS 24.301, section 7.3.1, case a * Assigned value that does not match any PTI in use */ @@ -164,7 +164,7 @@ int esm_recv_pdn_connectivity_reject(int pti, int ebi, /* * EPS bearer identity checking */ - else if ( (ebi != ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(ebi) ) { + else if ( (ebi != ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(user->esm_ebr_data, ebi) ) { /* 3GPP TS 24.301, section 7.3.2, case a * Assigned or reserved EPS bearer identity value */ LOG_TRACE(WARNING, "ESM-SAP - Invalid EPS bearer identity (ebi=%d)", @@ -179,7 +179,7 @@ int esm_recv_pdn_connectivity_reject(int pti, int ebi, esm_cause = msg->esmcause; /* Execute the PDN connectivity procedure not accepted by the network */ - int rc = esm_proc_pdn_connectivity_reject(pti, &esm_cause); + int rc = esm_proc_pdn_connectivity_reject(user, pti, &esm_cause); if (rc != RETURNerror) { esm_cause = ESM_CAUSE_SUCCESS; @@ -206,7 +206,7 @@ int esm_recv_pdn_connectivity_reject(int pti, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_recv_pdn_disconnect_reject(int pti, int ebi, +int esm_recv_pdn_disconnect_reject(nas_user_t *user, int pti, int ebi, const pdn_disconnect_reject_msg *msg) { LOG_FUNC_IN; @@ -225,7 +225,7 @@ int esm_recv_pdn_disconnect_reject(int pti, int ebi, */ LOG_TRACE(WARNING, "ESM-SAP - Invalid PTI value (pti=%d)", pti); LOG_FUNC_RETURN (ESM_CAUSE_INVALID_PTI_VALUE); - } else if ( esm_pt_is_not_in_use(pti) ) { + } else if ( esm_pt_is_not_in_use(user->esm_pt_data, pti) ) { /* 3GPP TS 24.301, section 7.3.1, case b * Assigned value that does not match any PTI in use */ @@ -235,7 +235,7 @@ int esm_recv_pdn_disconnect_reject(int pti, int ebi, /* * EPS bearer identity checking */ - else if ( (ebi != ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(ebi) ) { + else if ( (ebi != ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(user->esm_ebr_data, ebi) ) { /* 3GPP TS 24.301, section 7.3.2, case b * Assigned or reserved EPS bearer identity value */ LOG_TRACE(WARNING, "ESM-SAP - Invalid EPS bearer identity (ebi=%d)", @@ -250,7 +250,7 @@ int esm_recv_pdn_disconnect_reject(int pti, int ebi, esm_cause = msg->esmcause; /* Execute the PDN disconnect procedure not accepted by the network */ - int rc = esm_proc_pdn_disconnect_reject(pti, &esm_cause); + int rc = esm_proc_pdn_disconnect_reject(user, pti, &esm_cause); if (rc != RETURNerror) { esm_cause = ESM_CAUSE_SUCCESS; @@ -278,12 +278,13 @@ int esm_recv_pdn_disconnect_reject(int pti, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_recv_activate_default_eps_bearer_context_request(int pti, int ebi, +int esm_recv_activate_default_eps_bearer_context_request(nas_user_t *user, int pti, int ebi, const activate_default_eps_bearer_context_request_msg *msg) { LOG_FUNC_IN; int esm_cause = ESM_CAUSE_SUCCESS; + esm_pt_data_t *esm_pt_data = user->esm_pt_data; LOG_TRACE(INFO, "ESM-SAP - Received Activate Default EPS Bearer Context " "Request message (pti=%d, ebi=%d)", pti, ebi); @@ -297,7 +298,7 @@ int esm_recv_activate_default_eps_bearer_context_request(int pti, int ebi, */ LOG_TRACE(WARNING, "ESM-SAP - Invalid PTI value (pti=%d)", pti); LOG_FUNC_RETURN (ESM_CAUSE_INVALID_PTI_VALUE); - } else if ( esm_pt_is_not_in_use(pti) ) { + } else if ( esm_pt_is_not_in_use(esm_pt_data, pti) ) { /* 3GPP TS 24.301, section 7.3.1, case g * Assigned value that does not match any PTI in use */ @@ -307,7 +308,7 @@ int esm_recv_activate_default_eps_bearer_context_request(int pti, int ebi, /* * EPS bearer identity checking */ - else if ( (ebi == ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(ebi) ) { + else if ( (ebi == ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(user->esm_ebr_data, ebi) ) { /* 3GPP TS 24.301, section 7.3.2, case g * Reserved or unassigned EPS bearer identity value */ @@ -369,14 +370,14 @@ int esm_recv_activate_default_eps_bearer_context_request(int pti, int ebi, } /* Execute the PDN connectivity procedure accepted by the network */ - int pid = esm_proc_pdn_connectivity_accept(pti, pdn_type, + int pid = esm_proc_pdn_connectivity_accept(user, pti, pdn_type, &msg->pdnaddress.pdnaddressinformation, &msg->accesspointname.accesspointnamevalue, &esm_cause); if (pid != RETURNerror) { /* Create local default EPS bearer context */ - int rc = esm_proc_default_eps_bearer_context_request(pid, ebi, &qos, + int rc = esm_proc_default_eps_bearer_context_request(user, pid, ebi, &qos, &esm_cause); if (rc != RETURNerror) { @@ -406,7 +407,7 @@ int esm_recv_activate_default_eps_bearer_context_request(int pti, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, +int esm_recv_activate_dedicated_eps_bearer_context_request(nas_user_t *user, int pti, int ebi, const activate_dedicated_eps_bearer_context_request_msg *msg) { LOG_FUNC_IN; @@ -414,6 +415,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, int esm_cause = ESM_CAUSE_SUCCESS; int i; int j; + esm_pt_data_t *esm_pt_data = user->esm_pt_data; LOG_TRACE(INFO, "ESM-SAP - Received Activate Dedicated EPS Bearer " "Context Request message (pti=%d, ebi=%d)", pti, ebi); @@ -427,7 +429,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, */ LOG_TRACE(WARNING, "ESM-SAP - Invalid PTI value (pti=%d)", pti); LOG_FUNC_RETURN (ESM_CAUSE_INVALID_PTI_VALUE); - } else if ( (pti != ESM_PT_UNASSIGNED) && esm_pt_is_not_in_use(pti) ) { + } else if ( (pti != ESM_PT_UNASSIGNED) && esm_pt_is_not_in_use(esm_pt_data, pti) ) { /* 3GPP TS 24.301, section 7.3.1, case i * Assigned value that does not match any PTI in use */ @@ -437,7 +439,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, /* * EPS bearer identity checking */ - else if ( (ebi == ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(ebi) ) { + else if ( (ebi == ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(user->esm_ebr_data, ebi) ) { /* 3GPP TS 24.301, section 7.3.2, case h * Reserved or unassigned EPS bearer identity value */ @@ -580,7 +582,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, } /* Execute the dedicated EPS bearer context activation procedure */ - int rc = esm_proc_dedicated_eps_bearer_context_request(ebi, + int rc = esm_proc_dedicated_eps_bearer_context_request(user, ebi, msg->linkedepsbeareridentity, &qos, &tft, &esm_cause); @@ -614,13 +616,14 @@ int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, ** Others: None ** ** ** ***************************************************************************/ -int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi, +int esm_recv_deactivate_eps_bearer_context_request(nas_user_t *user, int pti, int ebi, const deactivate_eps_bearer_context_request_msg *msg) { LOG_FUNC_IN; int rc = RETURNok; int esm_cause; + esm_pt_data_t *esm_pt_data = user->esm_pt_data; LOG_TRACE(INFO, "ESM-SAP - Received Deactivate EPS Bearer Context " "Request message (pti=%d, ebi=%d)", pti, ebi); @@ -634,7 +637,7 @@ int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi, */ LOG_TRACE(WARNING, "ESM-SAP - Invalid PTI value (pti=%d)", pti); LOG_FUNC_RETURN (ESM_CAUSE_INVALID_PTI_VALUE); - } else if ( esm_pt_is_not_in_use(pti) ) { + } else if ( esm_pt_is_not_in_use(esm_pt_data, pti) ) { /* 3GPP TS 24.301, section 7.3.1, case m * Assigned value does not match any PTI in use */ @@ -644,8 +647,8 @@ int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi, /* * EPS bearer identity checking */ - else if ( (ebi == ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(ebi) || - esm_ebr_is_not_in_use(ebi) ) { + else if ( (ebi == ESM_EBI_UNASSIGNED) || esm_ebr_is_reserved(user->esm_ebr_data, ebi) || + esm_ebr_is_not_in_use(user->esm_ebr_data, ebi) ) { /* 3GPP TS 24.301, section 7.3.2, case j * Reserved or unassigned EPS bearer identity value or, * assigned value that does not match an existing EPS bearer context @@ -665,12 +668,12 @@ int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi, /* Execute the PDN disconnect procedure accepted by the network */ if (pti != ESM_PT_UNASSIGNED) { - rc = esm_proc_pdn_disconnect_accept(pti, &esm_cause); + rc = esm_proc_pdn_disconnect_accept(esm_pt_data, pti, &esm_cause); } if (rc != RETURNerror) { /* Execute the EPS bearer context deactivation procedure */ - rc = esm_proc_eps_bearer_context_deactivate_request(ebi, &esm_cause); + rc = esm_proc_eps_bearer_context_deactivate_request(user, ebi, &esm_cause); if (rc != RETURNerror) { esm_cause = ESM_CAUSE_SUCCESS; diff --git a/openair3/NAS/UE/ESM/SAP/esm_recv.h b/openair3/NAS/UE/ESM/SAP/esm_recv.h index db65230e1e3ec546efa5c0238488690b2c8b6b3e..ae36d650e3c37310e90b517934011e0f07e46dc7 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_recv.h +++ b/openair3/NAS/UE/ESM/SAP/esm_recv.h @@ -42,6 +42,7 @@ Description Defines functions executed at the ESM Service Access #include "EsmStatus.h" #include "emmData.h" +#include "user_defs.h" #include "PdnConnectivityReject.h" #include "PdnDisconnectReject.h" @@ -88,23 +89,23 @@ int esm_recv_status(int pti, int ebi, const esm_status_msg *msg); * Transaction related messages * ---------------------------- */ -int esm_recv_pdn_connectivity_reject(int pti, int ebi, +int esm_recv_pdn_connectivity_reject(nas_user_t *user, int pti, int ebi, const pdn_connectivity_reject_msg *msg); -int esm_recv_pdn_disconnect_reject(int pti, int ebi, +int esm_recv_pdn_disconnect_reject(nas_user_t *user, int pti, int ebi, const pdn_disconnect_reject_msg *msg); /* * Messages related to EPS bearer contexts * --------------------------------------- */ -int esm_recv_activate_default_eps_bearer_context_request(int pti, int ebi, +int esm_recv_activate_default_eps_bearer_context_request(nas_user_t *user, int pti, int ebi, const activate_default_eps_bearer_context_request_msg *msg); -int esm_recv_activate_dedicated_eps_bearer_context_request(int pti, int ebi, +int esm_recv_activate_dedicated_eps_bearer_context_request(nas_user_t *user, int pti, int ebi, const activate_dedicated_eps_bearer_context_request_msg *msg); -int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi, +int esm_recv_deactivate_eps_bearer_context_request(nas_user_t *user, int pti, int ebi, const deactivate_eps_bearer_context_request_msg *msg); diff --git a/openair3/NAS/UE/ESM/SAP/esm_sap.c b/openair3/NAS/UE/ESM/SAP/esm_sap.c index 5ead95d5b416ab5cf290e65dbcb2dc6b02713690..7ff1e57380bbb20b1dfb8b444593edd202809e87 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_sap.c +++ b/openair3/NAS/UE/ESM/SAP/esm_sap.c @@ -63,9 +63,9 @@ Description Defines the ESM Service Access Points at which the EPS /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ -static int _esm_sap_recv(int msg_type, int is_standalone, +static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, const OctetString *req, OctetString *rsp, esm_sap_error_t *err); -static int _esm_sap_send(int msg_type, int is_standalone, int pti, int ebi, +static int _esm_sap_send(nas_user_t *user, int msg_type, int is_standalone, int pti, int ebi, const esm_sap_data_t *data, OctetString *rsp); @@ -95,12 +95,6 @@ static const char *_esm_sap_primitive_str[] = { "ESM_UNITDATA_IND", }; -/* - * Buffer used to encode ESM messages before being returned to the EPS - * Mobility Management sublayer in order to be sent onto the network - */ -#define ESM_SAP_BUFFER_SIZE 4096 -static char _esm_sap_buffer[ESM_SAP_BUFFER_SIZE]; /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -144,9 +138,11 @@ void esm_sap_initialize(void) ** Others: None ** ** ** ***************************************************************************/ -int esm_sap_send(esm_sap_t *msg) +int esm_sap_send(nas_user_t *user, esm_sap_t *msg) { LOG_FUNC_IN; + esm_data_t *esm_data = user->esm_data; + msg->send.value = esm_data->send_buffer; int rc = RETURNerror; int pid; @@ -172,7 +168,7 @@ int esm_sap_send(esm_sap_t *msg) } /* Define new PDN context */ - rc = esm_proc_pdn_connectivity(pdn_connect->cid, TRUE, + rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, TRUE, pdn_connect->pdn_type, &apn, pdn_connect->is_emergency, NULL); @@ -184,13 +180,13 @@ int esm_sap_send(esm_sap_t *msg) if (pdn_connect->is_defined) { unsigned int pti; /* Assign new procedure transaction identity */ - rc = esm_proc_pdn_connectivity(pdn_connect->cid, TRUE, + rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, TRUE, pdn_connect->pdn_type, NULL, pdn_connect->is_emergency, &pti); if (rc != RETURNerror) { /* Send PDN connectivity request */ - rc = _esm_sap_send(PDN_CONNECTIVITY_REQUEST, + rc = _esm_sap_send(user, PDN_CONNECTIVITY_REQUEST, msg->is_standalone, pti, EPS_BEARER_IDENTITY_UNASSIGNED, &msg->data, &msg->send); @@ -206,16 +202,16 @@ int esm_sap_send(esm_sap_t *msg) if ( msg->is_standalone && pdn_connect->is_defined ) { /* Undefine the specified PDN context */ - rc = esm_proc_pdn_connectivity(pdn_connect->cid, FALSE, + rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, FALSE, pdn_connect->pdn_type, NULL, pdn_connect->is_emergency, NULL); } else if (msg->recv != NULL) { /* The UE received a PDN connectivity reject message */ - rc = _esm_sap_recv(PDN_CONNECTIVITY_REJECT, msg->is_standalone, + rc = _esm_sap_recv(user, PDN_CONNECTIVITY_REJECT, msg->is_standalone, msg->recv, &msg->send, &msg->err); } else { /* The PDN connectivity procedure locally failed */ - rc = esm_proc_pdn_connectivity_failure(TRUE); + rc = esm_proc_pdn_connectivity_failure(user, TRUE); } } break; @@ -226,12 +222,12 @@ int esm_sap_send(esm_sap_t *msg) /* Get the procedure transaction identity and the EPS bearer * identity of the default bearer assigned to the PDN to * disconnect from */ - rc = esm_proc_pdn_disconnect(msg->data.pdn_disconnect.cid, + rc = esm_proc_pdn_disconnect(esm_data, msg->data.pdn_disconnect.cid, &pti, &ebi); if (rc != RETURNerror) { /* Send PDN disconnect request */ - rc = _esm_sap_send(PDN_DISCONNECT_REQUEST, TRUE, pti, ebi, + rc = _esm_sap_send(user, PDN_DISCONNECT_REQUEST, TRUE, pti, ebi, &msg->data, &msg->send); } } @@ -254,7 +250,7 @@ int esm_sap_send(esm_sap_t *msg) case ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REQ: /* The UE received activate default ESP bearer context request */ - rc = _esm_sap_recv(ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST, + rc = _esm_sap_recv(user, ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST, msg->is_standalone, msg->recv, &msg->send, &msg->err); break; @@ -264,10 +260,10 @@ int esm_sap_send(esm_sap_t *msg) * The activate default ESP bearer context accept message * has been successfully delivered to the other side */ - rc = esm_proc_default_eps_bearer_context_complete(); + rc = esm_proc_default_eps_bearer_context_complete(user->default_eps_bearer_context_data); if (rc != RETURNerror) { - rc = esm_proc_pdn_connectivity_complete(); + rc = esm_proc_pdn_connectivity_complete(user); } break; @@ -276,10 +272,10 @@ int esm_sap_send(esm_sap_t *msg) /* * Default ESP bearer context activation procedure locally failed */ - rc = esm_proc_default_eps_bearer_context_failure(); + rc = esm_proc_default_eps_bearer_context_failure(user); if (rc != RETURNerror) { - rc = esm_proc_pdn_connectivity_failure(FALSE); + rc = esm_proc_pdn_connectivity_failure(user, FALSE); } break; @@ -307,7 +303,7 @@ int esm_sap_send(esm_sap_t *msg) /* * Locally deactivate EPS bearer context */ - rc = esm_proc_eps_bearer_context_deactivate(TRUE, + rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, msg->data.eps_bearer_context_deactivate.ebi, &pid, &bid); } break; @@ -316,7 +312,7 @@ int esm_sap_send(esm_sap_t *msg) break; case ESM_UNITDATA_IND: - rc = _esm_sap_recv(-1, msg->is_standalone, msg->recv, + rc = _esm_sap_recv(user, -1, msg->is_standalone, msg->recv, &msg->send, &msg->err); break; @@ -358,10 +354,9 @@ int esm_sap_send(esm_sap_t *msg) ** turned upon ESM procedure completion ** ** err: Error code of the ESM procedure ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_sap_buffer ** ** ** ***************************************************************************/ -static int _esm_sap_recv(int msg_type, int is_standalone, +static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, const OctetString *req, OctetString *rsp, esm_sap_error_t *err) { @@ -439,7 +434,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone, * received from the MME */ esm_cause = esm_recv_activate_default_eps_bearer_context_request( - pti, ebi, + user, pti, ebi, &esm_msg.activate_default_eps_bearer_context_request); if ( (esm_cause == ESM_CAUSE_SUCCESS) || @@ -477,7 +472,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone, * received from the MME */ esm_cause = esm_recv_activate_dedicated_eps_bearer_context_request( - pti, ebi, + user, pti, ebi, &esm_msg.activate_dedicated_eps_bearer_context_request); if ( (esm_cause == ESM_CAUSE_SUCCESS) || @@ -517,7 +512,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone, * Process deactivate EPS bearer context request message * received from the MME */ - esm_cause = esm_recv_deactivate_eps_bearer_context_request(pti, ebi, + esm_cause = esm_recv_deactivate_eps_bearer_context_request(user, pti, ebi, &esm_msg.deactivate_eps_bearer_context_request); if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) || @@ -553,7 +548,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone, /* * Process PDN connectivity reject message received from the MME */ - esm_cause = esm_recv_pdn_connectivity_reject(pti, ebi, + esm_cause = esm_recv_pdn_connectivity_reject(user, pti, ebi, &esm_msg.pdn_connectivity_reject); if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) || @@ -576,7 +571,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone, /* * Process PDN disconnect reject message received from the MME */ - esm_cause = esm_recv_pdn_disconnect_reject(pti, ebi, + esm_cause = esm_recv_pdn_disconnect_reject(user, pti, ebi, &esm_msg.pdn_disconnect_reject); if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) || @@ -641,16 +636,13 @@ static int _esm_sap_recv(int msg_type, int is_standalone, if ( (rc != RETURNerror) && (esm_procedure != NULL) ) { /* Encode the returned ESM response message */ - int size = esm_msg_encode(&esm_msg, (uint8_t *)_esm_sap_buffer, + int size = esm_msg_encode(&esm_msg, rsp->value, ESM_SAP_BUFFER_SIZE); - if (size > 0) { - rsp->length = size; - rsp->value = (uint8_t *)(_esm_sap_buffer); - } + rsp->length = size; /* Complete the relevant ESM procedure */ - rc = (*esm_procedure)(is_standalone, ebi, rsp, triggered_by_ue); + rc = (*esm_procedure)(user, is_standalone, ebi, rsp, triggered_by_ue); if (is_discarded) { /* Return indication that received message has been discarded */ @@ -690,10 +682,9 @@ static int _esm_sap_recv(int msg_type, int is_standalone, ** Outputs: rsp: The encoded ESM response message to be re- ** ** turned upon ESM procedure completion ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_sap_buffer ** ** ** ***************************************************************************/ -static int _esm_sap_send(int msg_type, int is_standalone, +static int _esm_sap_send(nas_user_t *user, int msg_type, int is_standalone, int pti, int ebi, const esm_sap_data_t *data, OctetString *rsp) { @@ -771,18 +762,15 @@ static int _esm_sap_send(int msg_type, int is_standalone, if (rc != RETURNerror) { /* Encode the returned ESM response message */ - int size = esm_msg_encode(&esm_msg, (uint8_t *)_esm_sap_buffer, + int size = esm_msg_encode(&esm_msg, rsp->value, ESM_SAP_BUFFER_SIZE); - if (size > 0) { - rsp->length = size; - rsp->value = (uint8_t *)(_esm_sap_buffer); - } - + rsp->length = size; /* Execute the relevant ESM procedure */ if (esm_procedure) { - rc = (*esm_procedure)(is_standalone, pti, rsp, sent_by_ue); + rc = (*esm_procedure)(user, is_standalone, pti, rsp, sent_by_ue); } + } LOG_FUNC_RETURN(rc); diff --git a/openair3/NAS/UE/ESM/SAP/esm_sap.h b/openair3/NAS/UE/ESM/SAP/esm_sap.h index 7364a4b6610961099706a2e49141efed1de5f629..b464e18900a330bdaf05bb6b6998da2d69e164b9 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_sap.h +++ b/openair3/NAS/UE/ESM/SAP/esm_sap.h @@ -41,6 +41,7 @@ Description Defines the ESM Service Access Points at which the EPS #define __ESM_SAP_H__ #include "esm_sapDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -60,6 +61,6 @@ Description Defines the ESM Service Access Points at which the EPS void esm_sap_initialize(void); -int esm_sap_send(esm_sap_t *msg); +int esm_sap_send(nas_user_t *user, esm_sap_t *msg); #endif /* __ESM_SAP_H__*/ diff --git a/openair3/NAS/UE/ESM/esmData.h b/openair3/NAS/UE/ESM/esmData.h index 4a498b5d2e979ddcdd79fdd50f44f4b3b12396fd..7da659e801b2e9fec174c689f5817b1682299b6b 100644 --- a/openair3/NAS/UE/ESM/esmData.h +++ b/openair3/NAS/UE/ESM/esmData.h @@ -52,11 +52,23 @@ Description Defines internal private data handled by EPS Session /* Total number of active EPS bearers */ #define ESM_DATA_EPS_BEARER_TOTAL 11 +#define ESM_SAP_BUFFER_SIZE 4096 /****************************************************************************/ /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ +/* + * -------------------------------------------------------------------------- + * Internal data handled by the default EPS bearer context activation + * procedure in the UE + * -------------------------------------------------------------------------- + */ +typedef struct { + int ebi; /* EPS bearer identity of the default EPS bearer associated + * to the PDN connection to be activated */ +} default_eps_bearer_context_data_t; + /* * Minimal and maximal value of an EPS bearer identity: * The EPS Bearer Identity (EBI) identifies a message flow @@ -72,8 +84,6 @@ typedef enum { ESM_EBR_STATE_MAX } esm_ebr_state; - - /* * ----------------------- * EPS bearer context data @@ -172,6 +182,7 @@ typedef struct esm_data_context_s { } pdn[ESM_DATA_PDN_MAX+1]; esm_ebr_data_t ebr; + uint8_t send_buffer[ESM_SAP_BUFFER_SIZE]; } esm_data_context_t; /* @@ -185,27 +196,16 @@ typedef struct esm_data_context_s { */ typedef esm_data_context_t esm_data_t; - /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ -/* - * ESM internal data (used within ESM only) - * ---------------------------------------- - */ -esm_data_t _esm_data; - /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -extern char ip_addr_str[100]; - -extern char *esm_data_get_ipv4_addr(const OctetString *ip_addr); - -extern char *esm_data_get_ipv6_addr(const OctetString *ip_addr); - -extern char *esm_data_get_ipv4v6_addr(const OctetString *ip_addr); +char *esm_data_get_ipv4_addr(const OctetString *ip_addr, char *ret); +char *esm_data_get_ipv6_addr(const OctetString *ip_addr, char *ret); +char *esm_data_get_ipv4v6_addr(const OctetString *ip_addr, char *ret); #endif /* __ESMDATA_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_ebr.c b/openair3/NAS/UE/ESM/esm_ebr.c index 878f06c18439ce46f63aed921f434a7410195cff..330da2fb23660d2182b70a4faf7a103b1c2fe961 100644 --- a/openair3/NAS/UE/ESM/esm_ebr.c +++ b/openair3/NAS/UE/ESM/esm_ebr.c @@ -44,15 +44,13 @@ Description Defines functions used to handle state of EPS bearer contexts #include "esm_ebr.h" #include "commonDef.h" #include "nas_log.h" +#include "utils.h" /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ -#define ESM_EBR_NB_UE_MAX 1 - - /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ @@ -63,16 +61,6 @@ static const char *_esm_ebr_state_str[ESM_EBR_STATE_MAX] = { "BEARER CONTEXT ACTIVE", }; -/* - * ---------------------------------- - * List of EPS bearer contexts per UE - * ---------------------------------- - */ - -#if !defined(NAS_BUILT_IN_EPC) -static esm_ebr_data_t _esm_ebr_data[ESM_EBR_NB_UE_MAX]; -#endif - /* * ---------------------- * User notification data @@ -102,7 +90,7 @@ static const network_pdn_state_t _esm_ebr_pdn_state[2][2][2] = { /* Returns the index of the next available entry in the list of EPS bearer * context data */ -static int _esm_ebr_get_available_entry(unsigned int ueid); +static int _esm_ebr_get_available_entry(esm_ebr_data_t *esm_ebr_data); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -119,41 +107,46 @@ static int _esm_ebr_get_available_entry(unsigned int ueid); ** ** ** Outputs: None ** ** Return: None ** - ** Others: _esm_ebr_data ** ** ** ***************************************************************************/ -void esm_ebr_initialize( - esm_indication_callback_t cb -) + +esm_ebr_data_t *esm_ebr_initialize(void) { -#if !defined(NAS_BUILT_IN_EPC) - int ueid, i; LOG_FUNC_IN; - for (ueid = 0; ueid < ESM_EBR_NB_UE_MAX; ueid++) { - _esm_ebr_data[ueid].index = 0; + int i; + esm_ebr_data_t *esm_ebr_data = calloc_or_fail(sizeof(esm_ebr_data_t)); - /* Initialize EPS bearer context data */ - for (i = 0; i < ESM_EBR_DATA_SIZE + 1; i++) { - _esm_ebr_data[ueid].context[i] = NULL; - } + esm_ebr_data->index = 0; + + /* Initialize EPS bearer context data */ + for (i = 0; i < ESM_EBR_DATA_SIZE + 1; i++) { + esm_ebr_data->context[i] = NULL; } + LOG_FUNC_OUT; + return esm_ebr_data; +} + +void esm_ebr_register_callback(esm_indication_callback_t cb) +{ + + LOG_FUNC_IN; + /* Initialize the user notification callback */ _esm_ebr_callback = *cb; LOG_FUNC_OUT; -#endif } + /**************************************************************************** ** ** ** Name: esm_ebr_assign() ** ** ** ** Description: Assigns a new EPS bearer context ** ** ** - ** Inputs: ueid: Lower layers UE identifier ** ** ebi: Identity of the new EPS bearer context ** ** cid: Identifier of the PDN context the EPS bea- ** ** rer context is associated to ** @@ -165,18 +158,16 @@ void esm_ebr_initialize( ** Return: The identity of the new EPS bearer context ** ** if successfully assigned; ** ** the not assigned EBI (0) otherwise. ** - ** Others: _esm_ebr_data ** ** ** ***************************************************************************/ -int esm_ebr_assign(int ebi, int cid, int default_ebr) +int esm_ebr_assign(esm_ebr_data_t *esm_ebr_data, int ebi, int cid, int default_ebr) { esm_ebr_context_t *ebr_ctx = NULL; - unsigned int ueid = 0; int i; LOG_FUNC_IN; - ebr_ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]; + ebr_ctx = esm_ebr_data->context[ebi - ESM_EBI_MIN]; if (ebi != ESM_EBI_UNASSIGNED) { @@ -192,7 +183,7 @@ int esm_ebr_assign(int ebi, int cid, int default_ebr) i = ebi - ESM_EBI_MIN; } else { /* Search for an available EPS bearer identity */ - i = _esm_ebr_get_available_entry(ueid); + i = _esm_ebr_get_available_entry(esm_ebr_data); if (i < 0) { LOG_FUNC_RETURN(ESM_EBI_UNASSIGNED); @@ -211,10 +202,10 @@ int esm_ebr_assign(int ebi, int cid, int default_ebr) } - _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] = ebr_ctx; + esm_ebr_data->context[ebi - ESM_EBI_MIN] = ebr_ctx; /* Store the index of the next available EPS bearer identity */ - _esm_ebr_data[ueid].index = i + 1; + esm_ebr_data->index = i + 1; /* Set the EPS bearer identity */ ebr_ctx->ebi = ebi; @@ -235,7 +226,7 @@ int esm_ebr_assign(int ebi, int cid, int default_ebr) ** ** ** Description: Release the given EPS bearer identity ** ** ** - ** Inputs: ueid: Lower layers UE identifier ** + ** Inputs: ** ** ebi: The identity of the EPS bearer context to ** ** be released ** ** Others: None ** @@ -244,13 +235,11 @@ int esm_ebr_assign(int ebi, int cid, int default_ebr) ** Return: RETURNok if the EPS bearer context has ** ** been successfully released; ** ** RETURNerror otherwise. ** - ** Others: _esm_ebr_data ** ** ** ***************************************************************************/ -int esm_ebr_release( +int esm_ebr_release(esm_ebr_data_t *esm_ebr_data, int ebi) { - unsigned int ueid = 0; esm_ebr_context_t *ebr_ctx; LOG_FUNC_IN; @@ -260,7 +249,7 @@ int esm_ebr_release( } /* Get EPS bearer context data */ - ebr_ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]; + ebr_ctx = esm_ebr_data->context[ebi - ESM_EBI_MIN]; if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) { /* EPS bearer context not assigned */ @@ -290,7 +279,6 @@ int esm_ebr_release( ** Description: Set the status of the specified EPS bearer context to the ** ** given state ** ** ** - ** Inputs: ueid: Lower layers UE identifier ** ** ebi: The identity of the EPS bearer ** ** status: The new EPS bearer context status ** ** ue_requested: TRUE/FALSE if the modification of the EPS ** @@ -300,10 +288,9 @@ int esm_ebr_release( ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_ebr_data ** ** ** ***************************************************************************/ -int esm_ebr_set_status( +int esm_ebr_set_status(user_api_id_t *user_api_id, esm_ebr_data_t *esm_ebr_data, int ebi, esm_ebr_state status, int ue_requested) { esm_ebr_context_t *ebr_ctx; @@ -311,19 +298,13 @@ int esm_ebr_set_status( LOG_FUNC_IN; - unsigned int ueid = 0; - - if (ueid >= ESM_EBR_NB_UE_MAX) { - LOG_FUNC_RETURN (RETURNerror); - } - if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) { LOG_FUNC_RETURN (RETURNerror); } /* Get EPS bearer context data */ - ebr_ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]; + ebr_ctx = esm_ebr_data->context[ebi - ESM_EBI_MIN]; if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) { /* EPS bearer context not assigned */ @@ -344,7 +325,7 @@ int esm_ebr_set_status( /* * Notify the user that the state of the EPS bearer has changed */ - (*_esm_ebr_callback)(ebr_ctx->cid, + (*_esm_ebr_callback)(user_api_id, ebr_ctx->cid, _esm_ebr_pdn_state[ue_requested][ebr_ctx->is_default_ebr][status]); LOG_FUNC_RETURN (RETURNok); } @@ -360,9 +341,7 @@ int esm_ebr_set_status( ** Description: Get the current status value of the specified EPS bearer ** ** context ** ** ** - ** Inputs: ueid: Lower layers UE identifier ** ** ebi: The identity of the EPS bearer ** - ** Others: _esm_ebr_data ** ** ** ** Outputs: None ** ** Return: The current value of the EPS bearer con- ** @@ -371,26 +350,25 @@ int esm_ebr_set_status( ** ** ***************************************************************************/ -esm_ebr_state esm_ebr_get_status( +esm_ebr_state esm_ebr_get_status(esm_ebr_data_t *esm_ebr_data, int ebi) { - unsigned int ueid = 0; if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) { return (ESM_EBR_INACTIVE); } - if (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] == NULL) { + if (esm_ebr_data->context[ebi - ESM_EBI_MIN] == NULL) { /* EPS bearer context not allocated */ return (ESM_EBR_INACTIVE); } - if (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]->ebi != ebi) { + if (esm_ebr_data->context[ebi - ESM_EBI_MIN]->ebi != ebi) { /* EPS bearer context not assigned */ return (ESM_EBR_INACTIVE); } - return (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]->status); + return (esm_ebr_data->context[ebi - ESM_EBI_MIN]->status); } /**************************************************************************** @@ -408,7 +386,7 @@ esm_ebr_state esm_ebr_get_status( ** Others: None ** ** ** ***************************************************************************/ -int esm_ebr_is_reserved(int ebi) +int esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi) { return ( (ebi != ESM_EBI_UNASSIGNED) && (ebi < ESM_EBI_MIN) ); } @@ -420,23 +398,20 @@ int esm_ebr_is_reserved(int ebi) ** Description: Check whether the given EPS bearer identity does not ** ** match an assigned EBI value currently in use ** ** ** - ** Inputs: ueid: Lower layers UE identifier ** ** ebi: The identity of the EPS bearer ** - ** Others: _esm_ebr_data ** ** ** ** Outputs: None ** ** Return: TRUE, FALSE ** ** Others: None ** ** ** ***************************************************************************/ -int esm_ebr_is_not_in_use( +int esm_ebr_is_not_in_use(esm_ebr_data_t *esm_ebr_data, int ebi) { - unsigned int ueid = 0; return ( (ebi == ESM_EBI_UNASSIGNED) || - (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] == NULL) || - (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]->ebi) != ebi); + (esm_ebr_data->context[ebi - ESM_EBI_MIN] == NULL) || + (esm_ebr_data->context[ebi - ESM_EBI_MIN]->ebi) != ebi); } /****************************************************************************/ @@ -450,8 +425,6 @@ int esm_ebr_is_not_in_use( ** Description: Returns the index of the next available entry in the list ** ** of EPS bearer context data ** ** ** - ** Inputs: ueid: Lower layers UE identifier ** - ** Others: _esm_ebr_data ** ** ** ** Outputs: None ** ** Return: The index of the next available EPS bearer ** @@ -460,20 +433,20 @@ int esm_ebr_is_not_in_use( ** Others: None ** ** ** ***************************************************************************/ -static int _esm_ebr_get_available_entry(unsigned int ueid) +static int _esm_ebr_get_available_entry(esm_ebr_data_t *esm_ebr_data) { int i; - for (i = _esm_ebr_data[ueid].index; i < ESM_EBR_DATA_SIZE; i++) { - if (_esm_ebr_data[ueid].context[i] != NULL) { + for (i = esm_ebr_data->index; i < ESM_EBR_DATA_SIZE; i++) { + if (esm_ebr_data->context[i] != NULL) { continue; } return i; } - for (i = 0; i < _esm_ebr_data[ueid].index; i++) { - if (_esm_ebr_data[ueid].context[i] != NULL) { + for (i = 0; i < esm_ebr_data->index; i++) { + if (esm_ebr_data->context[i] != NULL) { continue; } diff --git a/openair3/NAS/UE/ESM/esm_ebr.h b/openair3/NAS/UE/ESM/esm_ebr.h index dd586319564a15e986e708cb54fe5a942a22a39f..8e1eaee1a4291dd76fcf66c37d4201efd419e9e9 100644 --- a/openair3/NAS/UE/ESM/esm_ebr.h +++ b/openair3/NAS/UE/ESM/esm_ebr.h @@ -42,8 +42,10 @@ Description Defines functions used to handle state of EPS bearer contexts #include "OctetString.h" #include "networkDef.h" +#include "esmData.h" #include "nas_timer.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -56,6 +58,13 @@ Description Defines functions used to handle state of EPS bearer contexts /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ +/* + * User notification callback, executed whenever a change of status with + * respect of PDN connection or EPS bearer context is notified by the EPS + * Session Management sublayer + */ +typedef int (*esm_indication_callback_t) (user_api_id_t *user_api_id, int, network_pdn_state_t); + /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ @@ -64,15 +73,17 @@ Description Defines functions used to handle state of EPS bearer contexts /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int esm_ebr_is_reserved(int ebi); +void esm_ebr_register_callback(esm_indication_callback_t cb); + +int esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi); -void esm_ebr_initialize(esm_indication_callback_t cb); -int esm_ebr_assign(int ebi, int cid, int default_ebr); -int esm_ebr_release(int ebi); +esm_ebr_data_t *esm_ebr_initialize(void); +int esm_ebr_assign(esm_ebr_data_t *esm_ebr_data, int ebi, int cid, int default_ebr); +int esm_ebr_release(esm_ebr_data_t *esm_ebr_data, int ebi); -int esm_ebr_set_status(int ebi, esm_ebr_state status, int ue_requested); -esm_ebr_state esm_ebr_get_status(int ebi); +int esm_ebr_set_status(user_api_id_t *user_api_id, esm_ebr_data_t *esm_ebr_data, int ebi, esm_ebr_state status, int ue_requested); +esm_ebr_state esm_ebr_get_status(esm_ebr_data_t *esm_ebr_data, int ebi); -int esm_ebr_is_not_in_use(int ebi); +int esm_ebr_is_not_in_use(esm_ebr_data_t *esm_ebr_data, int ebi); #endif /* __ESM_EBR_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.c b/openair3/NAS/UE/ESM/esm_ebr_context.c index cca1e06913db2da5c436408e13681467c132bd00..4700187da179a45ffef1388623a12539881b8673 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.c +++ b/openair3/NAS/UE/ESM/esm_ebr_context.c @@ -47,6 +47,7 @@ Description Defines functions used to handle EPS bearer contexts. #include "esm_ebr_context.h" #include "emm_sap.h" +#include "system.h" #if defined(ENABLE_ITTI) # include "assertions.h" @@ -82,36 +83,33 @@ static int _esm_ebr_context_check_precedence(const network_tft_t *, ** Description: Creates a new EPS bearer context to the PDN with the spe- ** ** cified PDN connection identifier ** ** ** - ** Inputs: ueid: UE identifier ** + ** Inputs: ** ** pid: PDN connection identifier ** ** ebi: EPS bearer identity ** ** is_default: TRUE if the new bearer is a default EPS ** ** bearer context ** ** esm_qos: EPS bearer level QoS parameters ** ** tft: Traffic flow template parameters ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The EPS bearer identity of the default EPS ** ** bearer associated to the new EPS bearer ** ** context if successfully created; ** ** UNASSIGN EPS bearer value otherwise. ** - ** Others: _esm_data ** ** ** ***************************************************************************/ int esm_ebr_context_create( - + esm_data_t *esm_data, int ueid, int pid, int ebi, int is_default, const network_qos_t *qos, const network_tft_t *tft) { int bid = 0; esm_data_context_t *esm_ctx = NULL; esm_pdn_t *pdn = NULL; - //unsigned int ueid = 0; LOG_FUNC_IN; - esm_ctx = &_esm_data; + esm_ctx = esm_data; bid = ESM_DATA_EPS_BEARER_MAX; @@ -209,7 +207,7 @@ int esm_ebr_context_create( char *netmask = NULL; char broadcast[INET_ADDRSTRLEN]; struct in_addr in_addr; - char command_line[128]; + char command_line[500]; int res; switch (pdn->type) { @@ -275,15 +273,32 @@ int esm_ebr_context_create( } res = sprintf(command_line, - "ifconfig oip1 %s netmask %s broadcast %s", - ipv4_addr, netmask, broadcast); - (void)res; /* avoid gcc warning "set but not used" */ - // AssertFatal((res > 0) && (res < 128), - // "error in system command line"); + "ifconfig oip%d %s netmask %s broadcast %s up && " + "ip rule add from %s/32 table %d && " + "ip rule add to %s/32 table %d && " + "ip route add default dev oip%d table %d", + ueid + 1, ipv4_addr, netmask, broadcast, + ipv4_addr, ueid + 201, + ipv4_addr, ueid + 201, + ueid + 1, ueid + 201); + if ( res<0 ) { + LOG_TRACE(WARNING, "ESM-PROC - Failed to system command string"); + } LOG_TRACE(INFO, "ESM-PROC - executing %s ", command_line); - if (system(command_line)) ; /* TODO: what to do? */ + /* Calling system() here disrupts UE's realtime processing in some cases. + * This may be because of the call to fork(), which, for some + * unidentified reason, interacts badly with other (realtime) threads. + * background_system() is a replacement mechanism relying on a + * background process that does the system() and reports result to + * the parent process (lte-softmodem, oaisim, ...). The background + * process is created very early in the life of the parent process. + * The processes interact through standard pipes. See + * common/utils/system.c for details. + */ + if (background_system(command_line) != 0) + LOG_TRACE(ERROR, "ESM-PROC - failed command '%s'", command_line); break; @@ -316,9 +331,8 @@ int esm_ebr_context_create( ** Description: Releases EPS bearer context entry previously allocated ** ** to the EPS bearer with the specified EPS bearer identity ** ** ** - ** Inputs: ueid: UE identifier ** + ** Inputs: ** ** ebi: EPS bearer identity ** - ** Others: _esm_data ** ** ** ** Outputs: pid: Identifier of the PDN connection entry the ** ** EPS bearer context belongs to ** @@ -327,22 +341,20 @@ int esm_ebr_context_create( ** Return: The EPS bearer identity associated to the ** ** EPS bearer context if successfully relea- ** ** sed; UNASSIGN EPS bearer value otherwise. ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -int esm_ebr_context_release( - +int esm_ebr_context_release(nas_user_t *user, int ebi, int *pid, int *bid) { int found = FALSE; esm_pdn_t *pdn = NULL; esm_data_context_t *esm_ctx; - - //unsigned int ueid = 0; + esm_ebr_data_t *esm_ebr_data = user->esm_ebr_data; + user_api_id_t *user_api_id = user->user_api_id; LOG_FUNC_IN; - esm_ctx = &_esm_data; + esm_ctx = user->esm_data; if (ebi != ESM_EBI_UNASSIGNED) { /* @@ -456,11 +468,11 @@ int esm_ebr_context_release( } /* Set the EPS bearer context state to INACTIVE */ - (void) esm_ebr_set_status(pdn->bearer[i]->ebi, + esm_ebr_set_status(user_api_id, esm_ebr_data, pdn->bearer[i]->ebi, ESM_EBR_INACTIVE, TRUE); /* Release EPS bearer data */ - (void) esm_ebr_release(pdn->bearer[i]->ebi); + esm_ebr_release(esm_ebr_data, pdn->bearer[i]->ebi); // esm_ebr_release() /* Release dedicated EPS bearer data */ @@ -492,7 +504,7 @@ int esm_ebr_context_release( emm_sap_t emm_sap; emm_sap.primitive = EMMESM_ESTABLISH_CNF; emm_sap.u.emm_esm.u.establish.is_attached = FALSE; - (void) emm_sap_send(&emm_sap); + (void) emm_sap_send(user, &emm_sap); } /* 3GPP TS 24.301, section 6.4.4.3, 6.4.4.6 * If due to the EPS bearer context deactivation only the PDN @@ -505,7 +517,7 @@ int esm_ebr_context_release( emm_sap.primitive = EMMESM_ESTABLISH_CNF; emm_sap.u.emm_esm.u.establish.is_attached = TRUE; emm_sap.u.emm_esm.u.establish.is_emergency = TRUE; - (void) emm_sap_send(&emm_sap); + (void) emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN (ebi); @@ -524,7 +536,6 @@ int esm_ebr_context_release( ** ** ** Inputs: ebi: The EPS bearer identity of the default EPS ** ** bearer context ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The identifier of the PDN connection entry ** @@ -533,22 +544,22 @@ int esm_ebr_context_release( ** Others: None ** ** ** ***************************************************************************/ -int esm_ebr_context_get_pid(int ebi) +int esm_ebr_context_get_pid(esm_data_t *esm_data, int ebi) { LOG_FUNC_IN; int pid; for (pid = 0; pid < ESM_DATA_PDN_MAX; pid++) { - if (_esm_data.pdn[pid].data == NULL) { + if (esm_data->pdn[pid].data == NULL) { continue; } - if (_esm_data.pdn[pid].data->bearer[0] == NULL) { + if (esm_data->pdn[pid].data->bearer[0] == NULL) { continue; } - if (_esm_data.pdn[pid].data->bearer[0]->ebi == ebi) { + if (esm_data->pdn[pid].data->bearer[0]->ebi == ebi) { break; } } @@ -576,14 +587,13 @@ int esm_ebr_context_get_pid(int ebi) ** tft: The traffic flow template (set of packet ** ** filters) to be checked ** ** operation: Traffic flow template operation ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ -int esm_ebr_context_check_tft(int pid, int ebi, +int esm_ebr_context_check_tft(esm_data_t *esm_data, int pid, int ebi, const network_tft_t *tft, esm_ebr_context_tft_t operation) { @@ -593,14 +603,14 @@ int esm_ebr_context_check_tft(int pid, int ebi, int i; if (pid < ESM_DATA_PDN_MAX) { - if (pid != _esm_data.pdn[pid].pid) { + if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier %d " "is not valid", pid); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-PROC - PDN connection %d has not been " "allocated", pid); } else if (operation == ESM_EBR_CONTEXT_TFT_CREATE) { - esm_pdn_t *pdn = _esm_data.pdn[pid].data; + esm_pdn_t *pdn = esm_data->pdn[pid].data; /* For each EPS bearer context associated to the PDN connection */ for (i = 0; i < pdn->n_bearers; i++) { diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.h b/openair3/NAS/UE/ESM/esm_ebr_context.h index 95d7b081d884402da2b6ddff5ec5364e8a8d696c..a0016555a30233a9d5a3718dacae227b6e369692 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.h +++ b/openair3/NAS/UE/ESM/esm_ebr_context.h @@ -39,6 +39,7 @@ Description Defines functions used to handle EPS bearer contexts. #define __ESM_EBR_CONTEXT_H__ #include "networkDef.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -65,14 +66,14 @@ typedef enum { /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int esm_ebr_context_create(int pid, int ebi, int is_default, +int esm_ebr_context_create(esm_data_t *esm_data, int ueid, int pid, int ebi, int is_default, const network_qos_t *qos, const network_tft_t *tft); -int esm_ebr_context_release(int ebi, int *pid, int *bid); +int esm_ebr_context_release(nas_user_t *user, int ebi, int *pid, int *bid); -int esm_ebr_context_get_pid(int ebi); +int esm_ebr_context_get_pid(esm_data_t *esm_data, int ebi); -int esm_ebr_context_check_tft(int pid, int ebi, const network_tft_t *tft, +int esm_ebr_context_check_tft(esm_data_t *esm_data, int pid, int ebi, const network_tft_t *tft, esm_ebr_context_tft_t operation); diff --git a/openair3/NAS/UE/ESM/esm_ip.c b/openair3/NAS/UE/ESM/esm_ip.c index f21305a1a0ca9c1862b4cec94fb0ac879d58f392..0743307f6e65d99f24146836019e33403501d079 100644 --- a/openair3/NAS/UE/ESM/esm_ip.c +++ b/openair3/NAS/UE/ESM/esm_ip.c @@ -22,45 +22,43 @@ #include "emmData.h" #include "esmData.h" -char ip_addr_str[100]; - -inline char *esm_data_get_ipv4_addr(const OctetString *ip_addr) +char *esm_data_get_ipv4_addr(const OctetString *ip_addr, char *ret) { if (ip_addr->length > 0) { - sprintf(ip_addr_str, "%u.%u.%u.%u", + sprintf(ret, "%u.%u.%u.%u", ip_addr->value[0], ip_addr->value[1], ip_addr->value[2], ip_addr->value[3]); - return ip_addr_str; + return ret; } return (NULL); } -inline char *esm_data_get_ipv6_addr(const OctetString *ip_addr) +char *esm_data_get_ipv6_addr(const OctetString *ip_addr, char *ret) { if (ip_addr->length > 0) { - sprintf(ip_addr_str, "%x%.2x:%x%.2x:%x%.2x:%x%.2x", + sprintf(ret, "%x%.2x:%x%.2x:%x%.2x:%x%.2x", ip_addr->value[0], ip_addr->value[1], ip_addr->value[2], ip_addr->value[3], ip_addr->value[4], ip_addr->value[5], ip_addr->value[6], ip_addr->value[7]); - return ip_addr_str; + return ret; } return (NULL); } -inline char *esm_data_get_ipv4v6_addr(const OctetString *ip_addr) +char *esm_data_get_ipv4v6_addr(const OctetString *ip_addr, char *ret) { if (ip_addr->length > 0) { - sprintf(ip_addr_str, "%u.%u.%u.%u / %x%.2x:%x%.2x:%x%.2x:%x%.2x", + sprintf(ret, "%u.%u.%u.%u / %x%.2x:%x%.2x:%x%.2x:%x%.2x", ip_addr->value[0], ip_addr->value[1], ip_addr->value[2], ip_addr->value[3], ip_addr->value[4], ip_addr->value[5], ip_addr->value[6], ip_addr->value[7], ip_addr->value[8], ip_addr->value[9], ip_addr->value[10], ip_addr->value[11]); - return ip_addr_str; + return ret; } return (NULL); diff --git a/openair3/NAS/UE/ESM/esm_main.c b/openair3/NAS/UE/ESM/esm_main.c index 74af9935aaaf0210088e900a514ae0daf691d61c..6c110abb52ea34f708e278198a6e37a5b577f118 100644 --- a/openair3/NAS/UE/ESM/esm_main.c +++ b/openair3/NAS/UE/ESM/esm_main.c @@ -40,11 +40,13 @@ Description Defines the EPS Session Management procedure call manager, #include "esm_main.h" #include "commonDef.h" #include "nas_log.h" +#include "utils.h" #include "emmData.h" #include "esmData.h" #include "esm_pt.h" #include "esm_ebr.h" +#include "user_defs.h" /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ @@ -69,35 +71,46 @@ Description Defines the EPS Session Management procedure call manager, ** ** ** Outputs: None ** ** Return: None ** - ** Others: _esm_data ** ** ** ***************************************************************************/ -void esm_main_initialize(esm_indication_callback_t cb) +void esm_main_initialize(nas_user_t *user, esm_indication_callback_t cb) { LOG_FUNC_IN; int i; + esm_data_t *esm_data = calloc_or_fail(sizeof(esm_data_t)); + user->esm_data = esm_data; + + default_eps_bearer_context_data_t *default_eps_bearer_context = calloc(1, sizeof(default_eps_bearer_context_data_t)); + if ( default_eps_bearer_context == NULL ) { + LOG_TRACE(ERROR, "ESM-MAIN - Can't malloc default_eps_bearer_context"); + exit(EXIT_FAILURE); + } + default_eps_bearer_context->ebi = ESM_EBI_UNASSIGNED; + user->default_eps_bearer_context_data = default_eps_bearer_context; /* Total number of active EPS bearer contexts */ - _esm_data.n_ebrs = 0; + esm_data->n_ebrs = 0; /* List of active PDN connections */ - _esm_data.n_pdns = 0; + esm_data->n_pdns = 0; for (i = 0; i < ESM_DATA_PDN_MAX + 1; i++) { - _esm_data.pdn[i].pid = -1; - _esm_data.pdn[i].is_active = FALSE; - _esm_data.pdn[i].data = NULL; + esm_data->pdn[i].pid = -1; + esm_data->pdn[i].is_active = FALSE; + esm_data->pdn[i].data = NULL; } /* Emergency bearer services indicator */ - _esm_data.emergency = FALSE; + esm_data->emergency = FALSE; /* Initialize the procedure transaction identity manager */ - esm_pt_initialize(); - /* Initialize the EPS bearer context manager */ - esm_ebr_initialize(cb); + user->esm_pt_data = esm_pt_initialize(); + /* Initialize the EPS bearer context manager */ + user->esm_ebr_data = esm_ebr_initialize(); + // FIXME only one callback for all user or many for many ? + esm_ebr_register_callback(cb); LOG_FUNC_OUT; } @@ -116,7 +129,7 @@ void esm_main_initialize(esm_indication_callback_t cb) ** Others: None ** ** ** ***************************************************************************/ -void esm_main_cleanup(void) +void esm_main_cleanup(esm_data_t *esm_data) { LOG_FUNC_IN; @@ -127,8 +140,8 @@ void esm_main_cleanup(void) /* De-activate EPS bearers and clean up PDN connections */ for (pid = 0; pid < ESM_DATA_PDN_MAX; pid++) { - if (_esm_data.pdn[pid].data) { - esm_pdn_t *pdn = _esm_data.pdn[pid].data; + if (esm_data->pdn[pid].data) { + esm_pdn_t *pdn = esm_data->pdn[pid].data; if (pdn->apn.length > 0) { free(pdn->apn.value); @@ -152,7 +165,7 @@ void esm_main_cleanup(void) } /* Release the PDN connection */ - free(_esm_data.pdn[pid].data); + free(esm_data->pdn[pid].data); } } } @@ -168,7 +181,6 @@ void esm_main_cleanup(void) ** a defined state at the same time ** ** ** ** Inputs: None ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The maximum number of PDN connections that ** @@ -176,7 +188,7 @@ void esm_main_cleanup(void) ** Others: None ** ** ** ***************************************************************************/ -int esm_main_get_nb_pdns_max(void) +int esm_main_get_nb_pdns_max(esm_data_t *esm_data) { LOG_FUNC_IN; @@ -190,18 +202,17 @@ int esm_main_get_nb_pdns_max(void) ** Description: Get the number of active PDN connections ** ** ** ** Inputs: None ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: The number of active PDN connections ** ** Others: None ** ** ** ***************************************************************************/ -int esm_main_get_nb_pdns(void) +int esm_main_get_nb_pdns(esm_data_t *esm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_esm_data.n_pdns); + LOG_FUNC_RETURN (esm_data->n_pdns); } /**************************************************************************** @@ -212,7 +223,6 @@ int esm_main_get_nb_pdns(void) ** vices is established ** ** ** ** Inputs: None ** - ** Others: _esm_data ** ** ** ** Outputs: None ** ** Return: TRUE if a PDN connection for emergency ** @@ -220,11 +230,11 @@ int esm_main_get_nb_pdns(void) ** Others: None ** ** ** ***************************************************************************/ -int esm_main_has_emergency(void) +int esm_main_has_emergency(esm_data_t *esm_data) { LOG_FUNC_IN; - LOG_FUNC_RETURN (_esm_data.emergency); + LOG_FUNC_RETURN (esm_data->emergency); } /**************************************************************************** @@ -234,7 +244,6 @@ int esm_main_has_emergency(void) ** Description: Get the status of the specified PDN connection ** ** ** ** Inputs: cid: PDN connection identifier ** - ** Others: _esm_data ** ** ** ** Outputs: state: TRUE if the current state of the PDN con- ** ** nection is ACTIVE; FALSE otherwise. ** @@ -245,28 +254,30 @@ int esm_main_has_emergency(void) ** Others: None ** ** ** ***************************************************************************/ -int esm_main_get_pdn_status(int cid, int *state) +int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state) { LOG_FUNC_IN; unsigned int pid = cid - 1; + esm_data_t *esm_data = user->esm_data; + esm_ebr_data_t *esm_ebr_data = user-> esm_ebr_data; if (pid >= ESM_DATA_PDN_MAX) { return (FALSE); - } else if (pid != _esm_data.pdn[pid].pid) { + } else if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(WARNING, "ESM-MAIN - PDN connection %d is not defined", cid); return (FALSE); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-MAIN - PDN connection %d has not been allocated", cid); return (FALSE); } - if (_esm_data.pdn[pid].data->bearer[0] != NULL) { + if (esm_data->pdn[pid].data->bearer[0] != NULL) { /* The status of a PDN connection is the status of the default EPS bearer * that has been assigned to this PDN connection at activation time */ - int ebi = _esm_data.pdn[pid].data->bearer[0]->ebi; - *state = (esm_ebr_get_status(ebi) == ESM_EBR_ACTIVE); + int ebi = esm_data->pdn[pid].data->bearer[0]->ebi; + *state = (esm_ebr_get_status(esm_ebr_data, ebi) == ESM_EBR_ACTIVE); } /* The PDN connection has not been activated yet */ @@ -280,7 +291,6 @@ int esm_main_get_pdn_status(int cid, int *state) ** Description: Get parameters defined for the specified PDN connection ** ** ** ** Inputs: cid: PDN connection identifier ** - ** Others: _esm_data ** ** ** ** Outputs: type: PDN connection type (IPv4, IPv6, IPv4v6) ** ** apn: Access Point logical Name in used ** @@ -290,7 +300,7 @@ int esm_main_get_pdn_status(int cid, int *state) ** Others: None ** ** ** ***************************************************************************/ -int esm_main_get_pdn(int cid, int *type, const char **apn, +int esm_main_get_pdn(esm_data_t *esm_data, int cid, int *type, const char **apn, int *is_emergency, int *is_active) { LOG_FUNC_IN; @@ -299,29 +309,29 @@ int esm_main_get_pdn(int cid, int *type, const char **apn, if (pid >= ESM_DATA_PDN_MAX) { return (RETURNerror); - } else if (pid != _esm_data.pdn[pid].pid) { + } else if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(WARNING, "ESM-MAIN - PDN connection %d is not defined", cid); return (RETURNerror); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-MAIN - PDN connection %d has not been allocated", cid); return (RETURNerror); } /* Get the PDN type */ - *type = _esm_data.pdn[pid].data->type; + *type = esm_data->pdn[pid].data->type; /* Get the Access Point Name */ - if (_esm_data.pdn[pid].data->apn.length > 0) { - *apn = (char *)(_esm_data.pdn[pid].data->apn.value); + if (esm_data->pdn[pid].data->apn.length > 0) { + *apn = (char *)(esm_data->pdn[pid].data->apn.value); } else { *apn = NULL; } /* Get the emergency bearer services indicator */ - *is_emergency = _esm_data.pdn[pid].data->is_emergency; + *is_emergency = esm_data->pdn[pid].data->is_emergency; /* Get the active PDN connection indicator */ - *is_active = _esm_data.pdn[pid].is_active; + *is_active = esm_data->pdn[pid].is_active; LOG_FUNC_RETURN (RETURNok); } @@ -334,7 +344,6 @@ int esm_main_get_pdn(int cid, int *type, const char **apn, ** tion ** ** ** ** Inputs: cid: PDN connection identifier ** - ** Others: _esm_data ** ** ** ** Outputs: ipv4adddr: IPv4 address ** ** ipv6adddr: IPv6 address ** @@ -342,7 +351,7 @@ int esm_main_get_pdn(int cid, int *type, const char **apn, ** Others: None ** ** ** ***************************************************************************/ -int esm_main_get_pdn_addr(int cid, const char **ipv4addr, const char **ipv6addr) +int esm_main_get_pdn_addr(esm_data_t *esm_data, int cid, const char **ipv4addr, const char **ipv6addr) { LOG_FUNC_IN; @@ -350,35 +359,30 @@ int esm_main_get_pdn_addr(int cid, const char **ipv4addr, const char **ipv6addr) if (pid >= ESM_DATA_PDN_MAX) { return (RETURNerror); - } else if (pid != _esm_data.pdn[pid].pid) { + } else if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(WARNING, "ESM-MAIN - PDN connection %d is not defined", cid); return (RETURNerror); - } else if (_esm_data.pdn[pid].data == NULL) { + } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-MAIN - PDN connection %d has not been allocated", cid); return (RETURNerror); - } else if (!_esm_data.pdn[pid].is_active) { + } else if (!esm_data->pdn[pid].is_active) { /* No any IP address has been assigned to this PDN connection */ return (RETURNok); } - if (_esm_data.pdn[pid].data->type == NET_PDN_TYPE_IPV4) { + if (esm_data->pdn[pid].data->type == NET_PDN_TYPE_IPV4) { /* Get IPv4 address */ - *ipv4addr = _esm_data.pdn[pid].data->ip_addr; - } else if (_esm_data.pdn[pid].data->type == NET_PDN_TYPE_IPV6) { + *ipv4addr = esm_data->pdn[pid].data->ip_addr; + } else if (esm_data->pdn[pid].data->type == NET_PDN_TYPE_IPV6) { /* Get IPv6 address */ - *ipv6addr = _esm_data.pdn[pid].data->ip_addr; + *ipv6addr = esm_data->pdn[pid].data->ip_addr; } else { /* IPv4v6 dual-stack terminal */ - *ipv4addr = _esm_data.pdn[pid].data->ip_addr; - *ipv6addr = _esm_data.pdn[pid].data->ip_addr+ESM_DATA_IPV4_ADDRESS_SIZE; + *ipv4addr = esm_data->pdn[pid].data->ip_addr; + *ipv6addr = esm_data->pdn[pid].data->ip_addr+ESM_DATA_IPV4_ADDRESS_SIZE; } LOG_FUNC_RETURN (RETURNok); } - -/****************************************************************************/ -/********************* L O C A L F U N C T I O N S *********************/ -/****************************************************************************/ - diff --git a/openair3/NAS/UE/ESM/esm_main.h b/openair3/NAS/UE/ESM/esm_main.h index d7346fdb0898c491595485e90e32137ecbf430b3..42381c8d5b15b89d97ab2d008289dd40f5768a9b 100644 --- a/openair3/NAS/UE/ESM/esm_main.h +++ b/openair3/NAS/UE/ESM/esm_main.h @@ -41,6 +41,9 @@ Description Defines the EPS Session Management procedure call manager, #define __ESM_MAIN_H__ #include "networkDef.h" +#include "esm_ebr.h" +#include "esmData.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -58,19 +61,19 @@ Description Defines the EPS Session Management procedure call manager, /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void esm_main_initialize(esm_indication_callback_t cb); +void esm_main_initialize(nas_user_t *user, esm_indication_callback_t cb); -void esm_main_cleanup(void); +void esm_main_cleanup(esm_data_t *esm_data); /* User's getter for PDN connections and EPS bearer contexts */ -int esm_main_get_nb_pdns_max(void); -int esm_main_get_nb_pdns(void); -int esm_main_has_emergency(void); -int esm_main_get_pdn_status(int cid, int *state); -int esm_main_get_pdn(int cid, int *type, const char **apn, int *is_emergency, +int esm_main_get_nb_pdns_max(esm_data_t *esm_data); +int esm_main_get_nb_pdns(esm_data_t *esm_data); +int esm_main_has_emergency(esm_data_t *esm_data); +int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state); +int esm_main_get_pdn(esm_data_t *esm_data, int cid, int *type, const char **apn, int *is_emergency, int *is_active); -int esm_main_get_pdn_addr(int cid, const char **ipv4addr, const char **ipv6addr); +int esm_main_get_pdn_addr(esm_data_t *esm_data, int cid, const char **ipv4addr, const char **ipv6addr); #endif /* __ESM_MAIN_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_proc.h b/openair3/NAS/UE/ESM/esm_proc.h index edbd926309380549b597c63a8dc2241b9de27430..3d7260b83b7400c8a8d140dc648c7937fa9c6194 100644 --- a/openair3/NAS/UE/ESM/esm_proc.h +++ b/openair3/NAS/UE/ESM/esm_proc.h @@ -43,6 +43,7 @@ Description Defines the EPS Session Management procedures executed at #include "OctetString.h" #include "emmData.h" #include "ProtocolConfigurationOptions.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -78,7 +79,7 @@ typedef enum { * Type of the ESM procedure callback executed when requested by the UE * or initiated by the network */ -typedef int (*esm_proc_procedure_t) (int, int, OctetString *, int); +typedef int (*esm_proc_procedure_t) (nas_user_t *user, int, int, OctetString *, int); /* EPS bearer level QoS parameters */ typedef network_qos_t esm_proc_qos_t; @@ -112,7 +113,7 @@ typedef struct { * -------------------------------------------------------------------------- */ int esm_proc_status_ind(int pti, int ebi, int *esm_cause); -int esm_proc_status(int is_standalone, int pti, OctetString *msg, +int esm_proc_status(nas_user_t *user, int is_standalone, int pti, OctetString *msg, int sent_by_ue); @@ -121,16 +122,16 @@ int esm_proc_status(int is_standalone, int pti, OctetString *msg, * PDN connectivity procedure * -------------------------------------------------------------------------- */ -int esm_proc_pdn_connectivity(int cid, int to_define, +int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int to_define, esm_proc_pdn_type_t pdn_type, const OctetString *apn, int is_emergency, unsigned int *pti); -int esm_proc_pdn_connectivity_request(int is_standalone, int pti, +int esm_proc_pdn_connectivity_request(nas_user_t *user, int is_standalone, int pti, OctetString *msg, int sent_by_ue); -int esm_proc_pdn_connectivity_accept(int pti, esm_proc_pdn_type_t pdn_type, +int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_type_t pdn_type, const OctetString *pdn_address, const OctetString *apn, int *esm_cause); -int esm_proc_pdn_connectivity_reject(int pti, int *esm_cause); -int esm_proc_pdn_connectivity_complete(void); -int esm_proc_pdn_connectivity_failure(int is_pending); +int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause); +int esm_proc_pdn_connectivity_complete(nas_user_t *user); +int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending); /* @@ -138,12 +139,12 @@ int esm_proc_pdn_connectivity_failure(int is_pending); * PDN disconnect procedure * -------------------------------------------------------------------------- */ -int esm_proc_pdn_disconnect(int cid, unsigned int *pti, unsigned int *ebi); -int esm_proc_pdn_disconnect_request(int is_standalone, int pti, +int esm_proc_pdn_disconnect(esm_data_t *esm_data, int cid, unsigned int *pti, unsigned int *ebi); +int esm_proc_pdn_disconnect_request(nas_user_t *user, int is_standalone, int pti, OctetString *msg, int sent_by_ue); -int esm_proc_pdn_disconnect_accept(int pti, int *esm_cause); -int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause); +int esm_proc_pdn_disconnect_accept(esm_pt_data_t *esm_pt_data, int pti, int *esm_cause); +int esm_proc_pdn_disconnect_reject(nas_user_t *user, int pti, int *esm_cause); /* * -------------------------------------------------------------------------- @@ -151,14 +152,14 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause); * -------------------------------------------------------------------------- */ -int esm_proc_default_eps_bearer_context_request(int pid, int ebi, +int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int ebi, const esm_proc_qos_t *esm_qos, int *esm_cause); -int esm_proc_default_eps_bearer_context_complete(void); -int esm_proc_default_eps_bearer_context_failure(void); +int esm_proc_default_eps_bearer_context_complete(default_eps_bearer_context_data_t *default_eps_bearer_context_data); +int esm_proc_default_eps_bearer_context_failure(nas_user_t *user); -int esm_proc_default_eps_bearer_context_accept(int is_standalone, int ebi, +int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered); -int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi, +int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered); /* @@ -167,12 +168,12 @@ int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi, * -------------------------------------------------------------------------- */ -int esm_proc_dedicated_eps_bearer_context_request(int ebi, int default_ebi, +int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int default_ebi, const esm_proc_qos_t *qos, const esm_proc_tft_t *tft, int *esm_cause); -int esm_proc_dedicated_eps_bearer_context_accept(int is_standalone, int ebi, +int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered); -int esm_proc_dedicated_eps_bearer_context_reject(int is_standalone, int ebi, +int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered); /* @@ -181,11 +182,11 @@ int esm_proc_dedicated_eps_bearer_context_reject(int is_standalone, int ebi, * -------------------------------------------------------------------------- */ -int esm_proc_eps_bearer_context_deactivate(int is_local, int ebi, int *pid, +int esm_proc_eps_bearer_context_deactivate(nas_user_t *user, int is_local, int ebi, int *pid, int *bid); -int esm_proc_eps_bearer_context_deactivate_request(int ebi, int *esm_cause); +int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, int *esm_cause); -int esm_proc_eps_bearer_context_deactivate_accept(int is_standalone, int ebi, +int esm_proc_eps_bearer_context_deactivate_accept(nas_user_t *user, int is_standalone, int ebi, OctetString *msg, int ue_triggered); #endif /* __ESM_PROC_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_pt.c b/openair3/NAS/UE/ESM/esm_pt.c index 8e819fbd0bb6a956931a0a42785d86fcb8f784f0..9f8e948954ba7537e2abf6ada2303ef8e046ebc3 100644 --- a/openair3/NAS/UE/ESM/esm_pt.c +++ b/openair3/NAS/UE/ESM/esm_pt.c @@ -37,9 +37,12 @@ Description Defines functions used to handle ESM procedure transactions. *****************************************************************************/ #include "esm_pt.h" +#include "esm_pt_defs.h" +#include "user_defs.h" #include "commonDef.h" #include "nas_log.h" +#include "utils.h" #include <stdlib.h> // malloc, free #include <string.h> // memcpy @@ -48,14 +51,6 @@ Description Defines functions used to handle ESM procedure transactions. /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ -/* - * Minimal and maximal value of a procedure transaction identity: - * The Procedure Transaction Identity (PTI) identifies bi-directional - * messages flows - */ -#define ESM_PTI_MIN (PROCEDURE_TRANSACTION_IDENTITY_FIRST) -#define ESM_PTI_MAX (PROCEDURE_TRANSACTION_IDENTITY_LAST) - /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ @@ -66,33 +61,9 @@ static const char *_esm_pt_state_str[ESM_PT_STATE_MAX] = { "PROCEDURE TRANSACTION PENDING" }; -/* - * -------------------------- - * Procedure transaction data - * -------------------------- - */ -typedef struct { - unsigned char pti; /* Procedure transaction identity */ - esm_pt_state status; /* Procedure transaction status */ - struct nas_timer_t timer; /* Retransmission timer */ - esm_pt_timer_data_t *args; /* Retransmission timer parameters data */ -} esm_pt_context_t; - -/* - * ------------------------------ - * List of procedure transactions - * ------------------------------ - */ -static struct { - unsigned char index; /* Index of the next procedure transaction - * identity to be used */ -#define ESM_PT_DATA_SIZE (ESM_PTI_MAX - ESM_PTI_MIN + 1) - esm_pt_context_t *context[ESM_PT_DATA_SIZE + 1]; -} _esm_pt_data; - /* Return the index of the next available entry in the list of procedure * transaction data */ -static int _esm_pt_get_available_entry(void); +static int _esm_pt_get_available_entry(esm_pt_data_t *esm_pt_data); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -109,22 +80,22 @@ static int _esm_pt_get_available_entry(void); ** ** ** Outputs: None ** ** Return: None ** - ** Others: _esm_pt_data ** ** ** ***************************************************************************/ -void esm_pt_initialize(void) +esm_pt_data_t *esm_pt_initialize(void) { LOG_FUNC_IN; - + esm_pt_data_t *esm_pt_data = calloc_or_fail(sizeof(esm_pt_data_t)); int i; - _esm_pt_data.index = 0; + esm_pt_data->index = 0; for (i = 0; i < ESM_PT_DATA_SIZE + 1; i++) { - _esm_pt_data.context[i] = NULL; + esm_pt_data->context[i] = NULL; } LOG_FUNC_OUT; + return esm_pt_data; } /**************************************************************************** @@ -140,43 +111,42 @@ void esm_pt_initialize(void) ** Return: The identity of the new procedure transac- ** ** tion when successfully assigned; ** ** the unassigned PTI (0) otherwise. ** - ** Others: _esm_pt_data ** ** ** ***************************************************************************/ -int esm_pt_assign(void) +int esm_pt_assign(esm_pt_data_t *esm_pt_data) { LOG_FUNC_IN; /* Search for an available procedure transaction identity */ - int i = _esm_pt_get_available_entry(); + int i = _esm_pt_get_available_entry(esm_pt_data); if (i < 0) { LOG_FUNC_RETURN (ESM_PT_UNASSIGNED); } /* Assign new procedure transaction */ - _esm_pt_data.context[i] = + esm_pt_data->context[i] = (esm_pt_context_t *)malloc(sizeof(esm_pt_context_t)); - if (_esm_pt_data.context[i] == NULL) { + if (esm_pt_data->context[i] == NULL) { LOG_FUNC_RETURN (ESM_PT_UNASSIGNED); } /* Store the index of the next available procedure transaction identity */ - _esm_pt_data.index = i + 1; + esm_pt_data->index = i + 1; /* An available procedure transaction identity is found */ - _esm_pt_data.context[i]->pti = i + ESM_PTI_MIN; + esm_pt_data->context[i]->pti = i + ESM_PTI_MIN; /* Set the procedure transaction status to INACTIVE */ - _esm_pt_data.context[i]->status = ESM_PT_INACTIVE; + esm_pt_data->context[i]->status = ESM_PT_INACTIVE; /* Disable the retransmission timer */ - _esm_pt_data.context[i]->timer.id = NAS_TIMER_INACTIVE_ID; + esm_pt_data->context[i]->timer.id = NAS_TIMER_INACTIVE_ID; /* Setup retransmission timer parameters */ - _esm_pt_data.context[i]->args = NULL; + esm_pt_data->context[i]->args = NULL; LOG_TRACE(INFO, "ESM-FSM - Procedure transaction identity %d assigned", - _esm_pt_data.context[i]->pti); - LOG_FUNC_RETURN (_esm_pt_data.context[i]->pti); + esm_pt_data->context[i]->pti); + LOG_FUNC_RETURN (esm_pt_data->context[i]->pti); } /**************************************************************************** @@ -193,10 +163,9 @@ int esm_pt_assign(void) ** Return: RETURNok if the procedure transaction iden-** ** tity has been successfully released; ** ** RETURNerror otherwise. ** - ** Others: _esm_pt_data ** ** ** ***************************************************************************/ -int esm_pt_release(int pti) +int esm_pt_release(esm_pt_data_t *esm_pt_data, int pti) { LOG_FUNC_IN; @@ -205,7 +174,7 @@ int esm_pt_release(int pti) } /* Get procedure transaction data */ - esm_pt_context_t *ctx = _esm_pt_data.context[pti - ESM_PTI_MIN]; + esm_pt_context_t *ctx = esm_pt_data->context[pti - ESM_PTI_MIN]; if ( (ctx == NULL) || (ctx->pti != pti) ) { /* Procedure transaction not assigned */ @@ -236,8 +205,8 @@ int esm_pt_release(int pti) } /* Release transaction procedure data */ - free(_esm_pt_data.context[pti - ESM_PTI_MIN]); - _esm_pt_data.context[pti - ESM_PTI_MIN] = NULL; + free(esm_pt_data->context[pti - ESM_PTI_MIN]); + esm_pt_data->context[pti - ESM_PTI_MIN] = NULL; LOG_TRACE(INFO, "ESM-FSM - Procedure transaction %d released", pti); @@ -261,20 +230,20 @@ int esm_pt_release(int pti) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_pt_data ** ** ** ***************************************************************************/ -int esm_pt_start_timer(int pti, const OctetString *msg, +int esm_pt_start_timer(nas_user_t *user, int pti, const OctetString *msg, long sec, nas_timer_callback_t cb) { LOG_FUNC_IN; + esm_pt_data_t *esm_pt_data = user->esm_pt_data; if ( (pti < ESM_PTI_MIN) || (pti > ESM_PTI_MAX) ) { LOG_FUNC_RETURN (RETURNerror); } /* Get procedure transaction data */ - esm_pt_context_t *ctx = _esm_pt_data.context[pti - ESM_PTI_MIN]; + esm_pt_context_t *ctx = esm_pt_data->context[pti - ESM_PTI_MIN]; if ( (ctx == NULL) || (ctx->pti != pti) ) { /* Procedure transaction not assigned */ @@ -291,6 +260,7 @@ int esm_pt_start_timer(int pti, const OctetString *msg, ctx->args = (esm_pt_timer_data_t *)malloc(sizeof(esm_pt_timer_data_t)); if (ctx->args) { + ctx->args->user = user; /* Set the EPS bearer identity */ ctx->args->pti = pti; /* Reset the retransmission counter */ @@ -332,10 +302,9 @@ int esm_pt_start_timer(int pti, const OctetString *msg, ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_pt_data ** ** ** ***************************************************************************/ -int esm_pt_stop_timer(int pti) +int esm_pt_stop_timer(esm_pt_data_t *esm_pt_data, int pti) { LOG_FUNC_IN; @@ -344,7 +313,7 @@ int esm_pt_stop_timer(int pti) } /* Get procedure transaction data */ - esm_pt_context_t *ctx = _esm_pt_data.context[pti - ESM_PTI_MIN]; + esm_pt_context_t *ctx = esm_pt_data->context[pti - ESM_PTI_MIN]; if ( (ctx == NULL) || (ctx->pti != pti) ) { /* Procedure transaction not assigned */ @@ -384,10 +353,9 @@ int esm_pt_stop_timer(int pti) ** ** ** Outputs: None ** ** Return: RETURNok, RETURNerror ** - ** Others: _esm_pt_data ** ** ** ***************************************************************************/ -int esm_pt_set_status(int pti, esm_pt_state status) +int esm_pt_set_status(esm_pt_data_t *esm_pt_data, int pti, esm_pt_state status) { LOG_FUNC_IN; @@ -398,7 +366,7 @@ int esm_pt_set_status(int pti, esm_pt_state status) } /* Get procedure transaction data */ - esm_pt_context_t *ctx = _esm_pt_data.context[pti - ESM_PTI_MIN]; + esm_pt_context_t *ctx = esm_pt_data->context[pti - ESM_PTI_MIN]; if ( (ctx == NULL) || (ctx->pti != pti) ) { /* Procedure transaction not assigned */ @@ -431,7 +399,6 @@ int esm_pt_set_status(int pti, esm_pt_state status) ** transaction ** ** ** ** Inputs: pti: The identity of the procedure transaction ** - ** Others: _esm_pt_data ** ** ** ** Outputs: None ** ** Return: The current value of the ESM procedure ** @@ -439,23 +406,23 @@ int esm_pt_set_status(int pti, esm_pt_state status) ** Others: None ** ** ** ***************************************************************************/ -esm_pt_state esm_pt_get_status(int pti) +esm_pt_state esm_pt_get_status(esm_pt_data_t *esm_pt_data, int pti) { if ( (pti < ESM_PTI_MIN) || (pti > ESM_PTI_MAX) ) { return (ESM_PT_INACTIVE); } - if (_esm_pt_data.context[pti - ESM_PTI_MIN] == NULL) { + if (esm_pt_data->context[pti - ESM_PTI_MIN] == NULL) { /* Procedure transaction not allocated */ return (ESM_PT_INACTIVE); } - if (_esm_pt_data.context[pti - ESM_PTI_MIN]->pti != pti) { + if (esm_pt_data->context[pti - ESM_PTI_MIN]->pti != pti) { /* Procedure transaction not assigned */ return (ESM_PT_INACTIVE); } - return (_esm_pt_data.context[pti - ESM_PTI_MIN]->status); + return (esm_pt_data->context[pti - ESM_PTI_MIN]->status); } /**************************************************************************** @@ -467,7 +434,6 @@ esm_pt_state esm_pt_get_status(int pti) ** given state ** ** ** ** Inputs: status: The PDN connection status ** - ** Others: _esm_pt_data ** ** ** ** Outputs: None ** ** Return: The procedure transaction identity of the ** @@ -476,18 +442,18 @@ esm_pt_state esm_pt_get_status(int pti) ** Others: None ** ** ** ***************************************************************************/ -int esm_pt_get_pending_pti(esm_pt_state status) +int esm_pt_get_pending_pti(esm_pt_data_t *esm_pt_data, esm_pt_state status) { LOG_FUNC_IN; int i; for (i = 0; i < ESM_PT_DATA_SIZE; i++) { - if (_esm_pt_data.context[i] == NULL) { + if (esm_pt_data->context[i] == NULL) { continue; } - if (_esm_pt_data.context[i]->status != status) { + if (esm_pt_data->context[i]->status != status) { continue; } @@ -496,7 +462,7 @@ int esm_pt_get_pending_pti(esm_pt_state status) } if (i < ESM_PT_DATA_SIZE) { - LOG_FUNC_RETURN (_esm_pt_data.context[i]->pti); + LOG_FUNC_RETURN (esm_pt_data->context[i]->pti); } /* PDN connection entry not found */ @@ -511,18 +477,17 @@ int esm_pt_get_pending_pti(esm_pt_state status) ** does not match an assigned PTI value currently in use ** ** ** ** Inputs: pti: The identity of the procedure transaction ** - ** Others: _esm_pt_data ** ** ** ** Outputs: None ** ** Return: TRUE, FALSE ** ** Others: None ** ** ** ***************************************************************************/ -int esm_pt_is_not_in_use(int pti) +int esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti) { return ( (pti == ESM_PT_UNASSIGNED) || - (_esm_pt_data.context[pti - ESM_PTI_MIN] == NULL) || - (_esm_pt_data.context[pti - ESM_PTI_MIN]->pti) != pti); + (esm_pt_data->context[pti - ESM_PTI_MIN] == NULL) || + (esm_pt_data->context[pti - ESM_PTI_MIN]->pti) != pti); } /**************************************************************************** @@ -557,7 +522,6 @@ int esm_pt_is_reserved(int pti) ** of procedure transaction data ** ** ** ** Inputs: None ** - ** Others: _esm_pt_data ** ** ** ** Outputs: None ** ** Return: The index of the next available procedure ** @@ -566,20 +530,20 @@ int esm_pt_is_reserved(int pti) ** Others: None ** ** ** ***************************************************************************/ -static int _esm_pt_get_available_entry(void) +static int _esm_pt_get_available_entry(esm_pt_data_t *esm_pt_data) { int i; - for (i = _esm_pt_data.index; i < ESM_PT_DATA_SIZE; i++) { - if (_esm_pt_data.context[i] != NULL) { + for (i = esm_pt_data->index; i < ESM_PT_DATA_SIZE; i++) { + if (esm_pt_data->context[i] != NULL) { continue; } return i; } - for (i = 0; i < _esm_pt_data.index; i++) { - if (_esm_pt_data.context[i] != NULL) { + for (i = 0; i < esm_pt_data->index; i++) { + if (esm_pt_data->context[i] != NULL) { continue; } diff --git a/openair3/NAS/UE/ESM/esm_pt.h b/openair3/NAS/UE/ESM/esm_pt.h index 7cc0c54780646403ae3c33fc3dbb23e898bd31b9..8b8693efdaf6bb6d78130e8b4c817a383af27640 100644 --- a/openair3/NAS/UE/ESM/esm_pt.h +++ b/openair3/NAS/UE/ESM/esm_pt.h @@ -40,6 +40,8 @@ Description Defines functions used to handle ESM procedure transactions. #include "OctetString.h" #include "nas_timer.h" +#include "user_defs.h" +#include "esm_pt_defs.h" #include "ProcedureTransactionIdentity.h" @@ -54,21 +56,6 @@ Description Defines functions used to handle ESM procedure transactions. /************************ G L O B A L T Y P E S ************************/ /****************************************************************************/ -/* Procedure transaction states */ -typedef enum { - ESM_PT_INACTIVE, /* No procedure transaction exists */ - ESM_PT_PENDING, /* The UE has initiated a procedure transaction - * towards the network */ - ESM_PT_STATE_MAX -} esm_pt_state; - -/* ESM message timer retransmission data */ -typedef struct { - unsigned char pti; /* Procedure transaction identity */ - unsigned int count; /* Retransmission counter */ - OctetString msg; /* Encoded ESM message to re-transmit */ -} esm_pt_timer_data_t; - /****************************************************************************/ /******************** G L O B A L V A R I A B L E S ********************/ /****************************************************************************/ @@ -79,19 +66,19 @@ typedef struct { int esm_pt_is_reserved(int pti); -void esm_pt_initialize(void); +esm_pt_data_t *esm_pt_initialize(void); -int esm_pt_assign(void); -int esm_pt_release(int pti); +int esm_pt_assign(esm_pt_data_t *esm_pt_data); +int esm_pt_release(esm_pt_data_t *esm_pt_data, int pti); -int esm_pt_start_timer(int pti, const OctetString *msg, long sec, +int esm_pt_start_timer(nas_user_t *user, int pti, const OctetString *msg, long sec, nas_timer_callback_t cb); -int esm_pt_stop_timer(int pti); +int esm_pt_stop_timer(esm_pt_data_t *esm_pt_data, int pti); -int esm_pt_set_status(int pti, esm_pt_state status); -esm_pt_state esm_pt_get_status(int pti); -int esm_pt_get_pending_pti(esm_pt_state status); +int esm_pt_set_status(esm_pt_data_t *esm_pt_data, int pti, esm_pt_state status); +esm_pt_state esm_pt_get_status(esm_pt_data_t *esm_pt_data, int pti); +int esm_pt_get_pending_pti(esm_pt_data_t *esm_pt_data, esm_pt_state status); -int esm_pt_is_not_in_use(int pti); +int esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti); #endif /* __ESM_PT_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_pt_defs.h b/openair3/NAS/UE/ESM/esm_pt_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..36cc52dda92da2a52d15f1b7d4b3bf3b5b8af6a3 --- /dev/null +++ b/openair3/NAS/UE/ESM/esm_pt_defs.h @@ -0,0 +1,63 @@ +#ifndef _ESM_PT_DEFS_H +#define _ESM_PT_DEFS_H + +#include "UTIL/nas_timer.h" +#include "IES/ProcedureTransactionIdentity.h" + +/****************************************************************************/ +/********************* G L O B A L C O N S T A N T S *******************/ +/****************************************************************************/ + +/* + * Minimal and maximal value of a procedure transaction identity: + * The Procedure Transaction Identity (PTI) identifies bi-directional + * messages flows + */ +#define ESM_PTI_MIN (PROCEDURE_TRANSACTION_IDENTITY_FIRST) +#define ESM_PTI_MAX (PROCEDURE_TRANSACTION_IDENTITY_LAST) + +/****************************************************************************/ +/************************ G L O B A L T Y P E S ************************/ +/****************************************************************************/ + +/* Procedure transaction states */ +typedef enum { + ESM_PT_INACTIVE, /* No procedure transaction exists */ + ESM_PT_PENDING, /* The UE has initiated a procedure transaction + * towards the network */ + ESM_PT_STATE_MAX +} esm_pt_state; + +/* ESM message timer retransmission data */ +typedef struct { + unsigned char pti; /* Procedure transaction identity */ + unsigned int count; /* Retransmission counter */ + OctetString msg; /* Encoded ESM message to re-transmit */ + void *user; /* user reference - void to avoid cyclic dependency */ +} esm_pt_timer_data_t; + +/* + * -------------------------- + * Procedure transaction data + * -------------------------- + */ +typedef struct { + unsigned char pti; /* Procedure transaction identity */ + esm_pt_state status; /* Procedure transaction status */ + struct nas_timer_t timer; /* Retransmission timer */ + esm_pt_timer_data_t *args; /* Retransmission timer parameters data */ +} esm_pt_context_t; + +/* + * ------------------------------ + * List of procedure transactions + * ------------------------------ + */ +typedef struct { + unsigned char index; /* Index of the next procedure transaction + * identity to be used */ +#define ESM_PT_DATA_SIZE (ESM_PTI_MAX - ESM_PTI_MIN + 1) + esm_pt_context_t *context[ESM_PT_DATA_SIZE + 1]; +} esm_pt_data_t; + +#endif diff --git a/openair3/NAS/UE/UEprocess.c b/openair3/NAS/UE/UEprocess.c index 20af58dac67563576cb9c9f425a7bd63987033ec..35d1b864898638bf469c29344e210952faa7bdba 100644 --- a/openair3/NAS/UE/UEprocess.c +++ b/openair3/NAS/UE/UEprocess.c @@ -46,6 +46,7 @@ #include "nas_user.h" #include "nas_network.h" #include "nas_parser.h" +#include "user_defs.h" #include <stdlib.h> // exit #include <poll.h> // poll @@ -69,9 +70,12 @@ static void *_nas_network_mngr(void *); static int _nas_set_signal_handler(int signal, void (handler)(int)); static void _nas_signal_handler(int signal); -static void _nas_clean(int usr_fd, int net_fd); +static void _nas_clean(user_api_id_t *user_api_id, int net_fd); uint8_t usim_test = 0; +// FIXME user must be set up with right itti message instance +// FIXME allocate user and initialize its fields +nas_user_t *user = NULL; /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -80,6 +84,8 @@ uint8_t usim_test = 0; /****************************************************************************/ int main(int argc, const char *argv[]) { + // FIXME allocate and put it in user + user_api_id_t *user_api_id = NULL; /* * Get the command line options */ @@ -108,19 +114,19 @@ int main(int argc, const char *argv[]) /* * Initialize the User interface */ - if (user_api_initialize (uhost, uport, devpath, devparams) != RETURNok) { + if (user_api_initialize (user_api_id, uhost, uport, devpath, devparams) != RETURNok) { LOG_TRACE (ERROR, "UE-MAIN - user_api_initialize() failed"); exit (EXIT_FAILURE); } - int user_fd = user_api_get_fd (); + int user_fd = user_api_get_fd (user_api_id); /* * Initialize the Network interface */ if (network_api_initialize (nhost, nport) != RETURNok) { LOG_TRACE (ERROR, "UE-MAIN - network_api_initialize() failed"); - user_api_close (user_fd); + user_api_close (user_api_id); exit (EXIT_FAILURE); } @@ -129,7 +135,7 @@ int main(int argc, const char *argv[]) /* * Initialize the NAS contexts */ - nas_user_initialize (&user_api_emm_callback, &user_api_esm_callback, + nas_user_initialize (user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); nas_network_initialize (); @@ -157,7 +163,7 @@ int main(int argc, const char *argv[]) if (pthread_create (&user_mngr, &attr, _nas_user_mngr, &user_fd) != 0) { LOG_TRACE (ERROR, "UE-MAIN - " "Failed to create the user management thread"); - user_api_close (user_fd); + user_api_close (user_api_id); network_api_close (network_fd); exit (EXIT_FAILURE); } @@ -171,7 +177,7 @@ int main(int argc, const char *argv[]) &network_fd) != 0) { LOG_TRACE (ERROR, "UE-MAIN - " "Failed to create the network management thread"); - user_api_close (user_fd); + user_api_close (user_api_id); network_api_close (network_fd); exit (EXIT_FAILURE); } @@ -184,12 +190,12 @@ int main(int argc, const char *argv[]) */ while ((user_fd != -1) && (network_fd != -1)) { poll (NULL, 0, NAS_SLEEP_TIMEOUT); - user_fd = user_api_get_fd (); + user_fd = user_api_get_fd (user_api_id); network_fd = network_api_get_fd (); } /* Termination cleanup */ - _nas_clean (user_fd, network_fd); + _nas_clean (user_api_id, network_fd); LOG_TRACE (WARNING, "UE-MAIN - NAS main process exited"); @@ -218,6 +224,7 @@ static void *_nas_user_mngr(void *args) { LOG_FUNC_IN; + pthread_setname_np( pthread_self(), "nas_user_mngr"); int exit_loop = FALSE; int *fd = (int *) args; @@ -226,11 +233,11 @@ static void *_nas_user_mngr(void *args) /* User receiving loop */ while (!exit_loop) { - exit_loop = nas_user_receive_and_process(fd, NULL); + exit_loop = nas_user_receive_and_process(user, NULL); } /* Close the connection to the user application layer */ - user_api_close (*fd); + user_api_close (user->user_api_id); LOG_TRACE (WARNING, "UE-MAIN - " "The user connection endpoint manager exited"); @@ -291,7 +298,7 @@ static void *_nas_network_mngr(void *args) } /* Process the network data message */ - ret_code = nas_network_process_data (network_message_id, + ret_code = nas_network_process_data (user, network_message_id, network_api_get_data ()); if (ret_code != RETURNok) { @@ -379,7 +386,8 @@ static void _nas_signal_handler(int signal) LOG_FUNC_IN; LOG_TRACE (WARNING, "UE-MAIN - Signal %d received", signal); - _nas_clean (user_api_get_fd (), network_api_get_fd ()); + // FIXME acces to global + _nas_clean (user->user_api_id, network_api_get_fd ()); exit (EXIT_SUCCESS); LOG_FUNC_OUT @@ -400,17 +408,19 @@ static void _nas_signal_handler(int signal) ** Others: None ** ** ** ***************************************************************************/ -static void _nas_clean(int usr_fd, int net_fd) +static void _nas_clean(user_api_id_t *user_api_id, int net_fd) { LOG_FUNC_IN; LOG_TRACE (INFO, "UE-MAIN - Perform EMM and ESM cleanup"); - nas_network_cleanup (); + // FIXME nas_network_cleanup depends on nas_user_t + // Why this program should interfere like that with oaisim ? + //nas_network_cleanup (); LOG_TRACE (INFO, "UE-MAIN - " "Closing user connection %d and network connection %d", - usr_fd, net_fd); - user_api_close (usr_fd); + user_api_get_fd (user_api_id), net_fd); + user_api_close (user_api_id); network_api_close (net_fd); LOG_FUNC_OUT diff --git a/openair3/NAS/UE/nas_itti_messaging.c b/openair3/NAS/UE/nas_itti_messaging.c index 7667ad50a438b95892355a31c86b98b39c5f6e71..b6b2126dfb4800863a44473ac6dddb157416cd2b 100644 --- a/openair3/NAS/UE/nas_itti_messaging.c +++ b/openair3/NAS/UE/nas_itti_messaging.c @@ -213,7 +213,7 @@ int nas_itti_kenb_refresh_req(const Byte_t kenb[32]) return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p); } -int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat) +int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id) { MessageDef *message_p; @@ -230,10 +230,10 @@ int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat) plmnID.MCCdigit1, plmnID.MCCdigit2, plmnID.MCCdigit3, plmnID.MNCdigit1, plmnID.MNCdigit2, plmnID.MNCdigit3); - return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p); + return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + user_id, message_p); } -int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data, uint32_t length) +int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data, uint32_t length, int user_id) { MessageDef *message_p; @@ -255,10 +255,10 @@ int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t plmnID.MCCdigit1, plmnID.MCCdigit2, plmnID.MCCdigit3, plmnID.MNCdigit1, plmnID.MNCdigit2, plmnID.MNCdigit3); - return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p); + return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + user_id, message_p); } -int nas_itti_ul_data_req(const uint32_t ue_id, void *const data, const uint32_t length) +int nas_itti_ul_data_req(const uint32_t ue_id, void *const data, const uint32_t length, int user_id) { MessageDef *message_p; @@ -268,10 +268,10 @@ int nas_itti_ul_data_req(const uint32_t ue_id, void *const data, const uint32_t NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = data; NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = length; - return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p); + return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + user_id, message_p); } -int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, const nas_error_code_t errCode) +int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, const nas_error_code_t errCode, int user_id) { MessageDef *message_p; @@ -287,5 +287,5 @@ int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, NULL,0, "0 NAS_RAB_ESTABLI_RSP MME code %u m-TMSI %u rb id %u status %u", s_tmsi.MMEcode, s_tmsi.m_tmsi,rabID, errCode ); - return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p); + return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + user_id, message_p); } diff --git a/openair3/NAS/UE/nas_itti_messaging.h b/openair3/NAS/UE/nas_itti_messaging.h index 22c09f109b3be64977db004b3d12579f5ff2b688..f4f1f184143cc7e64f54293f04e9bb731da07b12 100644 --- a/openair3/NAS/UE/nas_itti_messaging.h +++ b/openair3/NAS/UE/nas_itti_messaging.h @@ -50,12 +50,12 @@ int nas_itti_protected_msg( int nas_itti_kenb_refresh_req(const Byte_t kenb[32]); -int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat); +int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id); -int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data_pP, uint32_t lengthP); +int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data_pP, uint32_t lengthP, int user_id); -int nas_itti_ul_data_req(const uint32_t ue_idP, void *const data_pP, const uint32_t lengthP); +int nas_itti_ul_data_req(const uint32_t ue_idP, void *const data_pP, const uint32_t lengthP, int user_id); -int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, const nas_error_code_t errCode); +int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, const nas_error_code_t errCode, int user_id); # endif #endif /* NAS_ITTI_MESSAGING_H_ */ diff --git a/openair3/NAS/UE/nas_network.c b/openair3/NAS/UE/nas_network.c index f3ee3d2955c5ed67dab2b9ba020cdb4873544edf..6ca4a34c7ffaa13b85d9cabe8dd4f160f84fa72c 100644 --- a/openair3/NAS/UE/nas_network.c +++ b/openair3/NAS/UE/nas_network.c @@ -43,6 +43,7 @@ Description NAS procedure functions triggered by the network #include "as_message.h" #include "nas_proc.h" +#include "user_defs.h" /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ @@ -91,11 +92,11 @@ void nas_network_initialize(void) ** Others: None ** ** ** ***************************************************************************/ -void nas_network_cleanup(void) +void nas_network_cleanup(nas_user_t *user) { LOG_FUNC_IN; - nas_proc_cleanup(); + nas_proc_cleanup(user); LOG_FUNC_OUT; } @@ -118,7 +119,7 @@ void nas_network_cleanup(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_network_process_data(int msg_id, const void *data) +int nas_network_process_data(nas_user_t *user, int msg_id, const void *data) { LOG_FUNC_IN; @@ -142,7 +143,7 @@ int nas_network_process_data(int msg_id, const void *data) /* Received cell information confirm */ const cell_info_cnf_t *info = &msg->msg.cell_info_cnf; int cell_found = (info->errCode == AS_SUCCESS); - rc = nas_proc_cell_info(cell_found, info->tac, + rc = nas_proc_cell_info(user, cell_found, info->tac, info->cellID, info->rat, info->rsrp, info->rsrq); break; @@ -160,12 +161,12 @@ int nas_network_process_data(int msg_id, const void *data) if ( (confirm->errCode == AS_SUCCESS) || (confirm->errCode == AS_TERMINATED_NAS) ) { - rc = nas_proc_establish_cnf(confirm->nasMsg.data, + rc = nas_proc_establish_cnf(user, confirm->nasMsg.data, confirm->nasMsg.length); } else { LOG_TRACE(WARNING, "NET-MAIN - " "Initial NAS message not delivered"); - rc = nas_proc_establish_rej(); + rc = nas_proc_establish_rej(user); } break; @@ -173,7 +174,7 @@ int nas_network_process_data(int msg_id, const void *data) case AS_NAS_RELEASE_IND: /* Received NAS signalling connection releaase indication */ - rc = nas_proc_release_ind(msg->msg.nas_release_ind.cause); + rc = nas_proc_release_ind(user, msg->msg.nas_release_ind.cause); break; case AS_UL_INFO_TRANSFER_CNF: @@ -182,9 +183,9 @@ int nas_network_process_data(int msg_id, const void *data) if (msg->msg.ul_info_transfer_cnf.errCode != AS_SUCCESS) { LOG_TRACE(WARNING, "NET-MAIN - " "Uplink NAS message not delivered"); - rc = nas_proc_ul_transfer_rej(); + rc = nas_proc_ul_transfer_rej(user); } else { - rc = nas_proc_ul_transfer_cnf(); + rc = nas_proc_ul_transfer_cnf(user); } break; @@ -192,7 +193,7 @@ int nas_network_process_data(int msg_id, const void *data) case AS_DL_INFO_TRANSFER_IND: { const dl_info_transfer_ind_t *info = &msg->msg.dl_info_transfer_ind; /* Received downlink data transfer indication */ - rc = nas_proc_dl_transfer_ind(info->nasMsg.data, + rc = nas_proc_dl_transfer_ind(user, info->nasMsg.data, info->nasMsg.length); break; } diff --git a/openair3/NAS/UE/nas_network.h b/openair3/NAS/UE/nas_network.h index 363f63c5ab16d2d4f3fe851b0b4dfe8d9c5f0206..fb05c8dd2a044b1c84a1ceb6c3891aa789960d60 100644 --- a/openair3/NAS/UE/nas_network.h +++ b/openair3/NAS/UE/nas_network.h @@ -40,6 +40,8 @@ Description NAS procedure functions triggered by the network #ifndef __NAS_NETWORK_H__ #define __NAS_NETWORK_H__ +#include "user_defs.h" + /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ /****************************************************************************/ @@ -59,9 +61,9 @@ Description NAS procedure functions triggered by the network void nas_network_initialize(void); -void nas_network_cleanup(void); +void nas_network_cleanup(nas_user_t *user); -int nas_network_process_data(int command_id, const void *data); +int nas_network_process_data(nas_user_t *user, int command_id, const void *data); const void *nas_network_get_data(void); diff --git a/openair3/NAS/UE/nas_proc.c b/openair3/NAS/UE/nas_proc.c index 79b66269955616bb74db6659ac7bc5df75c33484..97ecea8e5a7b4ca09b8eeb9653e7797ce021d73f 100644 --- a/openair3/NAS/UE/nas_proc.c +++ b/openair3/NAS/UE/nas_proc.c @@ -38,6 +38,8 @@ Description NAS procedure call manager #include "nas_proc.h" #include "nas_log.h" +#include "nas_user.h" +#include "utils.h" #include "emm_main.h" #include "emm_sap.h" @@ -62,20 +64,9 @@ Description NAS procedure call manager #define NAS_PROC_RSRQ_UNKNOWN 255 #define NAS_PROC_RSRP_UNKNOWN 255 -/* - * Local NAS data - */ -static struct { - /* EPS capibility status */ - int EPS_capability_status; - /* Reference signal received quality */ - int rsrq; - /* Reference signal received power */ - int rsrp; -} _nas_proc_data; - -static int _nas_proc_activate(int cid, int apply_to_all); -static int _nas_proc_deactivate(int cid, int apply_to_all); + +static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all); +static int _nas_proc_deactivate(nas_user_t *user, int cid, int apply_to_all); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -97,21 +88,24 @@ static int _nas_proc_deactivate(int cid, int apply_to_all); ** Others: _nas_proc_data ** ** ** ***************************************************************************/ -void nas_proc_initialize(emm_indication_callback_t emm_cb, +void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, esm_indication_callback_t esm_cb, const char *imei) { LOG_FUNC_IN; /* Initialize local NAS data */ - _nas_proc_data.EPS_capability_status = FALSE; - _nas_proc_data.rsrq = NAS_PROC_RSRQ_UNKNOWN; - _nas_proc_data.rsrp = NAS_PROC_RSRP_UNKNOWN; + user->proc.EPS_capability_status = FALSE; + user->proc.rsrq = NAS_PROC_RSRQ_UNKNOWN; + user->proc.rsrp = NAS_PROC_RSRP_UNKNOWN; + + user->authentication_data = calloc_or_fail(sizeof(authentication_data_t)); + user->security_data = calloc_or_fail( sizeof(security_data_t)); /* Initialize the EMM procedure manager */ - emm_main_initialize(emm_cb, imei); + emm_main_initialize(user, emm_cb, imei); /* Initialize the ESM procedure manager */ - esm_main_initialize(esm_cb); + esm_main_initialize(user, esm_cb); LOG_FUNC_OUT; } @@ -131,12 +125,12 @@ void nas_proc_initialize(emm_indication_callback_t emm_cb, ** Others: None ** ** ** ***************************************************************************/ -void nas_proc_cleanup(void) +void nas_proc_cleanup(nas_user_t *user) { LOG_FUNC_IN; /* Detach the UE from the EPS network */ - int rc = nas_proc_detach(TRUE); + int rc = nas_proc_detach(user, TRUE); if (rc != RETURNok) { LOG_TRACE(ERROR, "NAS-PROC - Failed to detach from the network"); @@ -144,10 +138,10 @@ void nas_proc_cleanup(void) /* Perform the EPS Mobility Manager's clean up procedure */ - emm_main_cleanup(); + emm_main_cleanup(user); /* Perform the EPS Session Manager's clean up procedure */ - esm_main_cleanup(); + esm_main_cleanup(user->esm_data); LOG_FUNC_OUT; } @@ -172,7 +166,7 @@ void nas_proc_cleanup(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_enable_s1_mode(void) +int nas_proc_enable_s1_mode(nas_user_t *user) { LOG_FUNC_IN; @@ -183,9 +177,9 @@ int nas_proc_enable_s1_mode(void) * Notify the EMM procedure call manager that EPS capability * of the UE is enabled */ - _nas_proc_data.EPS_capability_status = TRUE; + user->proc.EPS_capability_status = TRUE; emm_sap.primitive = EMMREG_S1_ENABLED; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -205,7 +199,7 @@ int nas_proc_enable_s1_mode(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_disable_s1_mode(void) +int nas_proc_disable_s1_mode(nas_user_t *user) { LOG_FUNC_IN; @@ -216,9 +210,9 @@ int nas_proc_disable_s1_mode(void) * Notify the EMM procedure call manager that EPS capability * of the UE is disabled */ - _nas_proc_data.EPS_capability_status = FALSE; + user->proc.EPS_capability_status = FALSE; emm_sap.primitive = EMMREG_S1_DISABLED; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -238,11 +232,11 @@ int nas_proc_disable_s1_mode(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_eps(int *stat) +int nas_proc_get_eps(nas_user_t *user, int *stat) { LOG_FUNC_IN; - *stat = _nas_proc_data.EPS_capability_status; + *stat = user->proc.EPS_capability_status; LOG_FUNC_RETURN (RETURNok); } @@ -261,11 +255,11 @@ int nas_proc_get_eps(int *stat) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_imsi(char *imsi_str) +int nas_proc_get_imsi(emm_data_t *emm_data, char *imsi_str) { LOG_FUNC_IN; - const imsi_t *imsi = emm_main_get_imsi(); + const imsi_t *imsi = emm_main_get_imsi(emm_data); if (imsi != NULL) { int offset = 0; @@ -309,11 +303,11 @@ int nas_proc_get_imsi(char *imsi_str) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_msisdn(char *msisdn_str, int *ton_npi) +int nas_proc_get_msisdn(nas_user_t *user, char *msisdn_str, int *ton_npi) { LOG_FUNC_IN; - const msisdn_t *msisdn = emm_main_get_msisdn(); + const msisdn_t *msisdn = emm_main_get_msisdn(user); if (msisdn != NULL) { union { @@ -358,12 +352,12 @@ int nas_proc_get_msisdn(char *msisdn_str, int *ton_npi) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_signal_quality(int *rsrq, int *rsrp) +int nas_proc_get_signal_quality(nas_user_t *user, int *rsrq, int *rsrp) { LOG_FUNC_IN; - *rsrq = _nas_proc_data.rsrq; - *rsrp = _nas_proc_data.rsrp; + *rsrq = user->proc.rsrq; + *rsrp = user->proc.rsrp; LOG_FUNC_RETURN (RETURNok); } @@ -387,7 +381,7 @@ int nas_proc_get_signal_quality(int *rsrq, int *rsrp) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_register(int mode, int format, const network_plmn_t *oper, int AcT) +int nas_proc_register(nas_user_t *user, int mode, int format, const network_plmn_t *oper, int AcT) { LOG_FUNC_IN; @@ -396,7 +390,7 @@ int nas_proc_register(int mode, int format, const network_plmn_t *oper, int AcT) /* * Set the PLMN selection mode of operation */ - int index = emm_main_set_plmn_selection_mode(mode, format, oper, AcT); + int index = emm_main_set_plmn_selection_mode(user, mode, format, oper, AcT); if ( !(index < 0) ) { /* @@ -406,7 +400,7 @@ int nas_proc_register(int mode, int format, const network_plmn_t *oper, int AcT) emm_sap_t emm_sap; emm_sap.primitive = EMMREG_REGISTER_REQ; emm_sap.u.emm_reg.u.regist.index = index; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN (rc); @@ -426,7 +420,7 @@ int nas_proc_register(int mode, int format, const network_plmn_t *oper, int AcT) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_deregister(void) +int nas_proc_deregister(nas_user_t *user) { LOG_FUNC_IN; @@ -456,22 +450,22 @@ int nas_proc_deregister(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_reg_data(int *mode, int *selected, int format, +int nas_proc_get_reg_data(nas_user_t *user, int *mode, int *selected, int format, network_plmn_t *oper, int *AcT) { LOG_FUNC_IN; /* Get the PLMN selection mode of operation */ - *mode = emm_main_get_plmn_selection_mode(); + *mode = emm_main_get_plmn_selection_mode(user->emm_data); /* Get the currently selected operator */ - const char *oper_name = emm_main_get_selected_plmn(oper, format); + const char *oper_name = emm_main_get_selected_plmn(user->emm_plmn_list, user->emm_data, oper, format); if (oper_name != NULL) { /* An operator is currently selected */ *selected = TRUE; /* Get the supported Radio Access Technology */ - *AcT = emm_main_get_plmn_rat(); + *AcT = emm_main_get_plmn_rat(user->emm_data); } else { /* No any operator is selected */ *selected = FALSE; @@ -495,11 +489,11 @@ int nas_proc_get_reg_data(int *mode, int *selected, int format, ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_oper_list(const char **oper_list) +int nas_proc_get_oper_list(nas_user_t *user, const char **oper_list) { LOG_FUNC_IN; - int size = emm_main_get_plmn_list(oper_list); + int size = emm_main_get_plmn_list(user->emm_plmn_list, user->emm_data, oper_list); LOG_FUNC_RETURN (size); } @@ -520,11 +514,11 @@ int nas_proc_get_oper_list(const char **oper_list) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_reg_status(int *stat) +int nas_proc_get_reg_status(nas_user_t *user, int *stat) { LOG_FUNC_IN; - *stat = emm_main_get_plmn_status(); + *stat = emm_main_get_plmn_status(user->emm_data); LOG_FUNC_RETURN (RETURNok); } @@ -548,13 +542,13 @@ int nas_proc_get_reg_status(int *stat) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_loc_info(char *tac, char *ci, int *AcT) +int nas_proc_get_loc_info(nas_user_t *user, char *tac, char *ci, int *AcT) { LOG_FUNC_IN; - sprintf(tac, "%.4x", emm_main_get_plmn_tac()); // two byte - sprintf(ci, "%.8x", emm_main_get_plmn_ci()); // four byte - *AcT = emm_main_get_plmn_rat(); // E-UTRAN + sprintf(tac, "%.4x", emm_main_get_plmn_tac(user->emm_data)); // two byte + sprintf(ci, "%.8x", emm_main_get_plmn_ci(user->emm_data)); // four byte + *AcT = emm_main_get_plmn_rat(user->emm_data); // E-UTRAN LOG_FUNC_RETURN (RETURNok); } @@ -573,18 +567,18 @@ int nas_proc_get_loc_info(char *tac, char *ci, int *AcT) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_detach(int switch_off) +int nas_proc_detach(nas_user_t *user, int switch_off) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc = RETURNok; - if ( emm_main_is_attached() ) { + if ( emm_main_is_attached(user->emm_data) ) { /* Initiate an Detach procedure */ emm_sap.primitive = EMMREG_DETACH_INIT; emm_sap.u.emm_reg.u.detach.switch_off = switch_off; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN (rc); @@ -604,18 +598,18 @@ int nas_proc_detach(int switch_off) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_attach(void) +int nas_proc_attach(nas_user_t *user) { LOG_FUNC_IN; emm_sap_t emm_sap; int rc = RETURNok; - if ( !emm_main_is_attached() ) { + if ( !emm_main_is_attached(user->emm_data) ) { /* Initiate an Attach procedure */ emm_sap.primitive = EMMREG_ATTACH_INIT; emm_sap.u.emm_reg.u.attach.is_emergency = FALSE; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN (rc); @@ -636,11 +630,11 @@ int nas_proc_attach(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_attach_status(void) +int nas_proc_get_attach_status(nas_user_t *user) { LOG_FUNC_IN; - int is_attached = emm_main_is_attached(); + int is_attached = emm_main_is_attached(user->emm_data); LOG_FUNC_RETURN (is_attached); } @@ -659,11 +653,11 @@ int nas_proc_get_attach_status(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_pdn_range(void) +int nas_proc_get_pdn_range(esm_data_t *esm_data) { LOG_FUNC_IN; - int max_pdn_id = esm_main_get_nb_pdns_max(); + int max_pdn_id = esm_main_get_nb_pdns_max(esm_data); LOG_FUNC_RETURN (max_pdn_id); } @@ -684,7 +678,7 @@ int nas_proc_get_pdn_range(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_pdn_status(int *cids, int *states, int n_pdn_max) +int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_max) { LOG_FUNC_IN; @@ -692,13 +686,13 @@ int nas_proc_get_pdn_status(int *cids, int *states, int n_pdn_max) int n_defined_pdn = 0; /* Get the maximum number of supported PDN contexts */ - int n_pdn = esm_main_get_nb_pdns_max(); + int n_pdn = esm_main_get_nb_pdns_max(user->esm_data); /* For all PDN contexts */ for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) { /* Get the status of this PDN */ int state = FALSE; - int is_defined = esm_main_get_pdn_status(cid, &state); + int is_defined = esm_main_get_pdn_status(user, cid, &state); if (is_defined != FALSE) { /* This PDN has been defined */ @@ -728,7 +722,7 @@ int nas_proc_get_pdn_status(int *cids, int *states, int n_pdn_max) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_pdn_param(int *cids, int *types, const char **apns, +int nas_proc_get_pdn_param(esm_data_t *esm_data, int *cids, int *types, const char **apns, int n_pdn_max) { LOG_FUNC_IN; @@ -737,13 +731,13 @@ int nas_proc_get_pdn_param(int *cids, int *types, const char **apns, int n_defined_pdn = 0; /* Get the maximum number of supported PDN contexts */ - int n_pdn = esm_main_get_nb_pdns_max(); + int n_pdn = esm_main_get_nb_pdns_max(esm_data); /* For all PDN contexts */ for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) { int emergency, active; /* Get PDN connection parameters */ - int rc = esm_main_get_pdn(cid, types, apns, &emergency, &active); + int rc = esm_main_get_pdn(esm_data, cid, types, apns, &emergency, &active); if (rc != RETURNerror) { /* This PDN has been defined */ @@ -780,7 +774,7 @@ int nas_proc_get_pdn_param(int *cids, int *types, const char **apns, ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_pdn_addr(int cid, int *cids, const char **addr1, +int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **addr1, const char **addr2, int n_pdn_max) { LOG_FUNC_IN; @@ -790,7 +784,7 @@ int nas_proc_get_pdn_addr(int cid, int *cids, const char **addr1, if (cid > 0) { /* Get addresses assigned to the specified PDN */ - rc = esm_main_get_pdn_addr(cid, addr1, addr2); + rc = esm_main_get_pdn_addr(user->esm_data, cid, addr1, addr2); if (rc != RETURNerror) { *cids = cid; @@ -798,12 +792,12 @@ int nas_proc_get_pdn_addr(int cid, int *cids, const char **addr1, } } else if (cid < 0) { /* Get the maximum number of supported PDN contexts */ - int n_pdn = esm_main_get_nb_pdns_max(); + int n_pdn = esm_main_get_nb_pdns_max(user->esm_data); /* For all PDN contexts */ for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) { /* Get PDN connection addresses */ - rc = esm_main_get_pdn_addr(cid, addr1, addr2); + rc = esm_main_get_pdn_addr(user->esm_data, cid, addr1, addr2); if (rc != RETURNerror) { /* This PDN has been defined */ @@ -843,7 +837,7 @@ int nas_proc_get_pdn_addr(int cid, int *cids, const char **addr1, ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_set_pdn(int cid, int type, const char *apn, int ipv4_addr, +int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int ipv4_addr, int emergency, int p_cscf, int im_cn_signal) { LOG_FUNC_IN; @@ -862,7 +856,7 @@ int nas_proc_set_pdn(int cid, int type, const char *apn, int ipv4_addr, * Notify ESM that a new PDN context has to be defined for * the specified APN */ - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); LOG_FUNC_RETURN (rc); } @@ -881,7 +875,7 @@ int nas_proc_set_pdn(int cid, int type, const char *apn, int ipv4_addr, ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_reset_pdn(int cid) +int nas_proc_reset_pdn(nas_user_t *user, int cid) { LOG_FUNC_IN; @@ -895,7 +889,7 @@ int nas_proc_reset_pdn(int cid) /* * Notify ESM that the specified PDN context has to be undefined */ - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); LOG_FUNC_RETURN (rc); } @@ -915,7 +909,7 @@ int nas_proc_reset_pdn(int cid) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_deactivate_pdn(int cid) +int nas_proc_deactivate_pdn(nas_user_t *user, int cid) { LOG_FUNC_IN; @@ -923,15 +917,15 @@ int nas_proc_deactivate_pdn(int cid) if (cid > 0) { /* Deactivate only the specified PDN context */ - rc = _nas_proc_deactivate(cid, FALSE); + rc = _nas_proc_deactivate(user, cid, FALSE); } else { /* Do not deactivate the PDN connection established during initial * network attachment (identifier 1) */ cid = 2; /* Deactivate all active PDN contexts */ - while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max()+1)) { - rc = _nas_proc_deactivate(cid++, TRUE); + while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max(user->esm_data)+1)) { + rc = _nas_proc_deactivate(user, cid++, TRUE); } } @@ -954,20 +948,20 @@ int nas_proc_deactivate_pdn(int cid) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_activate_pdn(int cid) +int nas_proc_activate_pdn(nas_user_t *user, int cid) { LOG_FUNC_IN; int rc = RETURNok; - if ( !emm_main_is_attached() ) { + if ( !emm_main_is_attached(user->emm_data) ) { /* * If the UE is not attached to the network, perform EPS attach * procedure prior to attempt to request any PDN connectivity */ LOG_TRACE(WARNING, "NAS-PROC - UE is not attached to the network"); - rc = nas_proc_attach(); - } else if (emm_main_is_emergency()) { + rc = nas_proc_attach(user); + } else if (emm_main_is_emergency(user->emm_data)) { /* The UE is attached for emergency bearer services; It shall not * request a PDN connection to any other PDN */ LOG_TRACE(WARNING,"NAS-PROC - Attached for emergency bearer services"); @@ -977,13 +971,13 @@ int nas_proc_activate_pdn(int cid) if (rc != RETURNerror) { if (cid > 0) { /* Activate only the specified PDN context */ - rc = _nas_proc_activate(cid, FALSE); + rc = _nas_proc_activate(user, cid, FALSE); } else { cid = 1; /* Activate all defined PDN contexts */ - while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max()+1)) { - rc = _nas_proc_activate(cid++, TRUE); + while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max(user->esm_data)+1)) { + rc = _nas_proc_activate(user, cid++, TRUE); } } } @@ -1021,7 +1015,7 @@ int nas_proc_activate_pdn(int cid) ** Others: _nas_proc_data ** ** ** ***************************************************************************/ -int nas_proc_cell_info(int found, tac_t tac, ci_t ci, AcT_t AcT, +int nas_proc_cell_info(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t AcT, uint8_t rsrq, uint8_t rsrp) { LOG_FUNC_IN; @@ -1030,8 +1024,8 @@ int nas_proc_cell_info(int found, tac_t tac, ci_t ci, AcT_t AcT, int rc; /* Store LTE signal strength/quality measurement data */ - _nas_proc_data.rsrq = rsrq; - _nas_proc_data.rsrp = rsrp; + user->proc.rsrq = rsrq; + user->proc.rsrp = rsrp; /* * Notify the EMM procedure call manager that cell information @@ -1044,7 +1038,7 @@ int nas_proc_cell_info(int found, tac_t tac, ci_t ci, AcT_t AcT, emm_sap.u.emm_as.u.cell_info.tac = tac; emm_sap.u.emm_as.u.cell_info.cellID = ci; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -1066,7 +1060,7 @@ int nas_proc_cell_info(int found, tac_t tac, ci_t ci, AcT_t AcT, ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_establish_cnf(const Byte_t *data, uint32_t len) +int nas_proc_establish_cnf(nas_user_t *user, const Byte_t *data, uint32_t len) { LOG_FUNC_IN; @@ -1081,7 +1075,7 @@ int nas_proc_establish_cnf(const Byte_t *data, uint32_t len) emm_sap.primitive = EMMAS_ESTABLISH_CNF; emm_sap.u.emm_as.u.establish.NASmsg.length = len; emm_sap.u.emm_as.u.establish.NASmsg.value = (uint8_t *)data; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -1103,7 +1097,7 @@ int nas_proc_establish_cnf(const Byte_t *data, uint32_t len) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_establish_rej(void) +int nas_proc_establish_rej(nas_user_t *user) { LOG_FUNC_IN; @@ -1116,7 +1110,7 @@ int nas_proc_establish_rej(void) * from lower layers */ emm_sap.primitive = EMMAS_ESTABLISH_REJ; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -1136,7 +1130,7 @@ int nas_proc_establish_rej(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_release_ind(int cause) +int nas_proc_release_ind(nas_user_t *user, int cause) { LOG_FUNC_IN; @@ -1149,7 +1143,7 @@ int nas_proc_release_ind(int cause) */ emm_sap.primitive = EMMAS_RELEASE_IND; emm_sap.u.emm_as.u.release.cause = cause; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -1170,7 +1164,7 @@ int nas_proc_release_ind(int cause) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_ul_transfer_cnf(void) +int nas_proc_ul_transfer_cnf(nas_user_t *user) { LOG_FUNC_IN; @@ -1183,10 +1177,10 @@ int nas_proc_ul_transfer_cnf(void) * receiver side */ emm_sap.primitive = EMMAS_DATA_IND; - emm_sap.u.emm_as.u.data.ueid = 0; + emm_sap.u.emm_as.u.data.ueid = user->ueid; emm_sap.u.emm_as.u.data.delivered = TRUE; emm_sap.u.emm_as.u.data.NASmsg.length = 0; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -1207,7 +1201,7 @@ int nas_proc_ul_transfer_cnf(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_ul_transfer_rej(void) +int nas_proc_ul_transfer_rej(nas_user_t *user) { LOG_FUNC_IN; @@ -1220,10 +1214,10 @@ int nas_proc_ul_transfer_rej(void) * from lower layers */ emm_sap.primitive = EMMAS_DATA_IND; - emm_sap.u.emm_as.u.data.ueid = 0; + emm_sap.u.emm_as.u.data.ueid = user->ueid; emm_sap.u.emm_as.u.data.delivered = FALSE; emm_sap.u.emm_as.u.data.NASmsg.length = 0; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); } @@ -1244,7 +1238,7 @@ int nas_proc_ul_transfer_rej(void) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_dl_transfer_ind(const Byte_t *data, uint32_t len) +int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len) { LOG_FUNC_IN; @@ -1257,11 +1251,11 @@ int nas_proc_dl_transfer_ind(const Byte_t *data, uint32_t len) * indication has been received from the Access-Stratum sublayer */ emm_sap.primitive = EMMAS_DATA_IND; - emm_sap.u.emm_as.u.data.ueid = 0; + emm_sap.u.emm_as.u.data.ueid = user->ueid; emm_sap.u.emm_as.u.data.delivered = TRUE; emm_sap.u.emm_as.u.data.NASmsg.length = len; emm_sap.u.emm_as.u.data.NASmsg.value = (uint8_t *)data; - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(user, &emm_sap); } LOG_FUNC_RETURN (rc); @@ -1291,7 +1285,7 @@ int nas_proc_dl_transfer_ind(const Byte_t *data, uint32_t len) ** Others: None ** ** ** ***************************************************************************/ -static int _nas_proc_activate(int cid, int apply_to_all) +static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all) { LOG_FUNC_IN; @@ -1301,7 +1295,7 @@ static int _nas_proc_activate(int cid, int apply_to_all) esm_sap_t esm_sap; /* Get PDN context parameters */ - rc = esm_main_get_pdn(cid, &esm_sap.data.pdn_connect.pdn_type, + rc = esm_main_get_pdn(user->esm_data, cid, &esm_sap.data.pdn_connect.pdn_type, &esm_sap.data.pdn_connect.apn, &esm_sap.data.pdn_connect.is_emergency, &active); @@ -1323,7 +1317,7 @@ static int _nas_proc_activate(int cid, int apply_to_all) } if (esm_sap.data.pdn_connect.is_emergency) { - if (esm_main_has_emergency()) { + if (esm_main_has_emergency(user->esm_data)) { /* There is already a PDN connection for emergency * bearer services established; the UE shall not * request an additional PDN connection for emer- @@ -1342,7 +1336,7 @@ static int _nas_proc_activate(int cid, int apply_to_all) esm_sap.is_standalone = TRUE; esm_sap.data.pdn_connect.is_defined = TRUE; esm_sap.data.pdn_connect.cid = cid; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); LOG_FUNC_RETURN (rc); } @@ -1364,7 +1358,7 @@ static int _nas_proc_activate(int cid, int apply_to_all) ** Others: None ** ** ** ***************************************************************************/ -static int _nas_proc_deactivate(int cid, int apply_to_all) +static int _nas_proc_deactivate(nas_user_t *user, int cid, int apply_to_all) { LOG_FUNC_IN; @@ -1375,7 +1369,7 @@ static int _nas_proc_deactivate(int cid, int apply_to_all) int active = FALSE; /* Get PDN context parameters */ - rc = esm_main_get_pdn(cid, &pdn_type, &apn, &emergency, &active); + rc = esm_main_get_pdn(user->esm_data, cid, &pdn_type, &apn, &emergency, &active); if (rc != RETURNok) { /* No any context is defined for the specified PDN */ @@ -1393,7 +1387,7 @@ static int _nas_proc_deactivate(int cid, int apply_to_all) LOG_FUNC_RETURN (RETURNok); } - if (esm_main_get_nb_pdns() > 1) { + if (esm_main_get_nb_pdns(user->esm_data) > 1) { /* * Notify ESM that all EPS bearers towards the specified PDN * has to be released @@ -1401,7 +1395,7 @@ static int _nas_proc_deactivate(int cid, int apply_to_all) esm_sap_t esm_sap; esm_sap.primitive = ESM_PDN_DISCONNECT_REQ; esm_sap.data.pdn_disconnect.cid = cid; - rc = esm_sap_send(&esm_sap); + rc = esm_sap_send(user, &esm_sap); } else { /* For EPS, if an attempt is made to disconnect the last PDN * connection, then the MT responds with an error */ diff --git a/openair3/NAS/UE/nas_proc.h b/openair3/NAS/UE/nas_proc.h index 4514983df88d28f981c435469475fe83f9119028..bf8dec9e58a19e81986a3d0eb4f598ea9ae5ea47 100644 --- a/openair3/NAS/UE/nas_proc.h +++ b/openair3/NAS/UE/nas_proc.h @@ -40,6 +40,10 @@ Description NAS procedure call manager #include "commonDef.h" #include "networkDef.h" +#include "user_defs.h" +#include "emm_main.h" +#include "esm_ebr.h" +#include "esmData.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -57,10 +61,10 @@ Description NAS procedure call manager /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void nas_proc_initialize(emm_indication_callback_t emm_cb, +void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, esm_indication_callback_t esm_cb, const char *imei); -void nas_proc_cleanup(void); +void nas_proc_cleanup(nas_user_t *user); /* * -------------------------------------------------------------------------- @@ -68,39 +72,39 @@ void nas_proc_cleanup(void); * -------------------------------------------------------------------------- */ -int nas_proc_enable_s1_mode(void); -int nas_proc_disable_s1_mode(void); -int nas_proc_get_eps(int *stat); +int nas_proc_enable_s1_mode(nas_user_t *user); +int nas_proc_disable_s1_mode(nas_user_t *user); +int nas_proc_get_eps(nas_user_t *user, int *stat); -int nas_proc_get_imsi(char *imsi_str); -int nas_proc_get_msisdn(char *msisdn_str, int *ton_npi); +int nas_proc_get_imsi(emm_data_t *emm_data, char *imsi_str); +int nas_proc_get_msisdn(nas_user_t *user, char *msisdn_str, int *ton_npi); -int nas_proc_get_signal_quality(int *rsrq, int *rsrp); +int nas_proc_get_signal_quality(nas_user_t *user, int *rsrq, int *rsrp); -int nas_proc_register(int mode, int format, const network_plmn_t *oper, int AcT); -int nas_proc_deregister(void); -int nas_proc_get_reg_data(int *mode, int *selected, int format, +int nas_proc_register(nas_user_t *user, int mode, int format, const network_plmn_t *oper, int AcT); +int nas_proc_deregister(nas_user_t *user); +int nas_proc_get_reg_data(nas_user_t *user, int *mode, int *selected, int format, network_plmn_t *oper, int *AcT); -int nas_proc_get_oper_list(const char **oper_list); +int nas_proc_get_oper_list(nas_user_t *user, const char **oper_list); -int nas_proc_get_reg_status(int *stat); -int nas_proc_get_loc_info(char *tac, char *ci, int *AcT); +int nas_proc_get_reg_status(nas_user_t *user, int *stat); +int nas_proc_get_loc_info(nas_user_t *user, char *tac, char *ci, int *AcT); -int nas_proc_detach(int switch_off); -int nas_proc_attach(void); -int nas_proc_get_attach_status(void); +int nas_proc_detach(nas_user_t *user, int switch_off); +int nas_proc_attach(nas_user_t *user); +int nas_proc_get_attach_status(nas_user_t *user); -int nas_proc_reset_pdn(int cid); -int nas_proc_set_pdn(int cid, int type, const char *apn, int ipv4_addr, +int nas_proc_reset_pdn(nas_user_t *user, int cid); +int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int ipv4_addr, int emergency, int p_cscf, int im_cn_signal); -int nas_proc_get_pdn_range(void); -int nas_proc_get_pdn_status(int *cids, int *states, int n_pdn_max); -int nas_proc_get_pdn_param(int *cids, int *types, const char **apns, +int nas_proc_get_pdn_range(esm_data_t *esm_data); +int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_max); +int nas_proc_get_pdn_param(esm_data_t *esm_data, int *cids, int *types, const char **apns, int n_pdn_max); -int nas_proc_get_pdn_addr(int cid, int *cids, const char **addr1, +int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **addr1, const char **addr2, int n_addr_max); -int nas_proc_deactivate_pdn(int cid); -int nas_proc_activate_pdn(int cid); +int nas_proc_deactivate_pdn(nas_user_t *user, int cid); +int nas_proc_activate_pdn(nas_user_t *user, int cid); /* * -------------------------------------------------------------------------- @@ -108,17 +112,17 @@ int nas_proc_activate_pdn(int cid); * -------------------------------------------------------------------------- */ -int nas_proc_cell_info(int found, tac_t tac, ci_t ci, AcT_t rat, uint8_t rsrp, +int nas_proc_cell_info(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t rat, uint8_t rsrp, uint8_t rsrq); -int nas_proc_establish_cnf(const Byte_t *data, uint32_t len); -int nas_proc_establish_rej(void); +int nas_proc_establish_cnf(nas_user_t *user, const Byte_t *data, uint32_t len); +int nas_proc_establish_rej(nas_user_t *user); -int nas_proc_release_ind(int cause); +int nas_proc_release_ind(nas_user_t *user, int cause); -int nas_proc_ul_transfer_cnf(void); -int nas_proc_ul_transfer_rej(void); -int nas_proc_dl_transfer_ind(const Byte_t *data, uint32_t len); +int nas_proc_ul_transfer_cnf(nas_user_t *user); +int nas_proc_ul_transfer_rej(nas_user_t *user); +int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len); diff --git a/openair3/NAS/UE/nas_proc_defs.h b/openair3/NAS/UE/nas_proc_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..1ce2bfd929df7734eafd738df34787c388b263f6 --- /dev/null +++ b/openair3/NAS/UE/nas_proc_defs.h @@ -0,0 +1,43 @@ +#ifndef _NAS_PROC_DEFS_H +#define _NAS_PROC_DEFS_H + +/* + * Local NAS data + */ +typedef struct { + /* EPS capibility status */ + int EPS_capability_status; + /* Reference signal received quality */ + int rsrq; + /* Reference signal received power */ + int rsrp; +} proc_data_t; + +/* + * MT SIM pending status (see ETSI TS 127 007 V10.6.0, Note 2) + * Commands which interact with MT that are accepted when MT is pending SIM PIN, + * SIM PUK, or PH-SIM are: +CGMI, +CGMM, +CGMR, +CGSN, D112; (emergency call), + * +CPAS, +CFUN, +CPIN, +CPINR, +CDIS (read and test command only), and +CIND + * (read and test command only). +*/ +typedef enum { + NAS_USER_READY, /* MT is not pending for any password */ + NAS_USER_SIM_PIN, /* MT is waiting SIM PIN to be given */ + NAS_USER_SIM_PUK, /* MT is waiting SIM PUK to be given */ + NAS_USER_PH_SIM_PIN /* MT is waiting phone-to-SIM card + * password to be given */ +} nas_user_sim_status; + +/* + * The local UE context + */ +typedef struct { + /* Firmware version number */ + const char *version; + /* SIM pending status */ + nas_user_sim_status sim_status; + /* Level of functionality */ + int fun; +} nas_user_context_t; + +#endif diff --git a/openair3/NAS/UE/nas_ue_task.c b/openair3/NAS/UE/nas_ue_task.c index 9d097fc3897030e8491271e7cf89e472c4c95e2f..da9ae8879d90723902ad50d559f27a3e21aa022c 100644 --- a/openair3/NAS/UE/nas_ue_task.c +++ b/openair3/NAS/UE/nas_ue_task.c @@ -19,26 +19,32 @@ * contact@openairinterface.org */ +#include "utils.h" #if defined(ENABLE_ITTI) # include "assertions.h" # include "intertask_interface.h" # include "nas_ue_task.h" # include "UTIL/LOG/log.h" -# include "nas_user.h" +# include "user_defs.h" # include "user_api.h" # include "nas_parser.h" # include "nas_proc.h" # include "msc.h" +# include "memory.h" +#include "nas_user.h" + +// FIXME make command line option for NAS_UE_AUTOSTART # define NAS_UE_AUTOSTART 1 +// FIXME review these externs extern unsigned char NB_eNB_INST; extern unsigned char NB_UE_INST; -static int user_fd; +char *make_port_str_from_ueid(const char *base_port_str, int ueid); -static int nas_ue_process_events(struct epoll_event *events, int nb_events) +static int nas_ue_process_events(nas_user_container_t *users, struct epoll_event *events, int nb_events) { int event; int exit_loop = FALSE; @@ -48,8 +54,9 @@ static int nas_ue_process_events(struct epoll_event *events, int nb_events) for (event = 0; event < nb_events; event++) { if (events[event].events != 0) { /* If the event has not been yet been processed (not an itti message) */ - if (events[event].data.fd == user_fd) { - exit_loop = nas_user_receive_and_process(&user_fd, NULL); + nas_user_t *user = find_user_from_fd(users, events[event].data.fd); + if ( user != NULL ) { + exit_loop = nas_user_receive_and_process(user, NULL); } else { LOG_E(NAS, "[UE] Received an event from an unknown fd %d!\n", events[event].data.fd); } @@ -59,6 +66,24 @@ static int nas_ue_process_events(struct epoll_event *events, int nb_events) return (exit_loop); } +// Initialize user api id and port number +void nas_user_api_id_initialize(nas_user_t *user) { + user_api_id_t *user_api_id = calloc_or_fail(sizeof(user_api_id_t)); + user->user_api_id = user_api_id; + char *port = make_port_str_from_ueid(NAS_PARSER_DEFAULT_USER_PORT_NUMBER, user->ueid); + if ( port == NULL ) { + LOG_E(NAS, "[UE %d] can't get port from ueid!", user->ueid); + exit (EXIT_FAILURE); + } + if (user_api_initialize (user_api_id, NAS_PARSER_DEFAULT_USER_HOSTNAME, port, NULL, + NULL) != RETURNok) { + LOG_E(NAS, "[UE %d] user interface initialization failed!", user->ueid); + exit (EXIT_FAILURE); + } + free(port); + itti_subscribe_event_fd (TASK_NAS_UE, user_api_get_fd(user_api_id)); +} + void *nas_ue_task(void *args_p) { int nb_events; @@ -68,25 +93,45 @@ void *nas_ue_task(void *args_p) instance_t instance; unsigned int Mod_id; int result; + nas_user_container_t *users=args_p; itti_mark_task_ready (TASK_NAS_UE); MSC_START_USE(); /* Initialize UE NAS (EURECOM-NAS) */ + for (int i=0; i < users->count; i++) { - /* Initialize user interface (to exchange AT commands with user process) */ - { - if (user_api_initialize (NAS_PARSER_DEFAULT_USER_HOSTNAME, NAS_PARSER_DEFAULT_USER_PORT_NUMBER, NULL, - NULL) != RETURNok) { - LOG_E(NAS, "[UE] user interface initialization failed!"); - exit (EXIT_FAILURE); - } + nas_user_t *user = &users->item[i]; + user->ueid=i; + + /* Get USIM data application filename */ + user->usim_data_store = memory_get_path_from_ueid(USIM_API_NVRAM_DIRNAME, USIM_API_NVRAM_FILENAME, user->ueid); + if ( user->usim_data_store == NULL ) { + LOG_E(NAS, "[UE %d] - Failed to get USIM data application filename", user->ueid); + exit(EXIT_FAILURE); + } + + /* Get UE's data pathname */ + user->user_nvdata_store = memory_get_path_from_ueid(USER_NVRAM_DIRNAME, USER_NVRAM_FILENAME, user->ueid); + if ( user->user_nvdata_store == NULL ) { + LOG_E(NAS, "[UE %d] - Failed to get USIM nvdata filename", user->ueid); + exit(EXIT_FAILURE); + } - user_fd = user_api_get_fd (); - itti_subscribe_event_fd (TASK_NAS_UE, user_fd); + /* Get EMM data pathname */ + user->emm_nvdata_store = memory_get_path_from_ueid(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME, user->ueid); + if ( user->emm_nvdata_store == NULL ) { + LOG_E(NAS, "[UE %d] - Failed to get EMM nvdata filename", user->ueid); + exit(EXIT_FAILURE); } + /* Initialize user interface (to exchange AT commands with user process) */ + nas_user_api_id_initialize(user); + /* allocate needed structures */ + user->user_at_commands = calloc_or_fail(sizeof(user_at_commands_t)); + user->at_response = calloc_or_fail(sizeof(at_response_t)); + user->lowerlayer_data = calloc_or_fail(sizeof(lowerlayer_data_t)); /* Initialize NAS user */ - nas_user_initialize (&user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); + nas_user_initialize (user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); } /* Set UE activation state */ @@ -105,6 +150,12 @@ void *nas_ue_task(void *args_p) msg_name = ITTI_MSG_NAME (msg_p); instance = ITTI_MSG_INSTANCE (msg_p); Mod_id = instance - NB_eNB_INST; + if (instance == INSTANCE_DEFAULT) { + printf("%s:%d: FATAL: instance is INSTANCE_DEFAULT, should not happen.\n", + __FILE__, __LINE__); + abort(); + } + nas_user_t *user = &users->item[Mod_id]; switch (ITTI_MSG_ID(msg_p)) { case INITIALIZE_MESSAGE: @@ -114,7 +165,7 @@ void *nas_ue_task(void *args_p) /* Send an activate modem command to NAS like UserProcess should do it */ char *user_data = "at+cfun=1\r"; - nas_user_receive_and_process (&user_fd, user_data); + nas_user_receive_and_process (user, user_data); } #endif break; @@ -134,7 +185,7 @@ void *nas_ue_task(void *args_p) { int cell_found = (NAS_CELL_SELECTION_CNF (msg_p).errCode == AS_SUCCESS); - nas_proc_cell_info (cell_found, NAS_CELL_SELECTION_CNF (msg_p).tac, + nas_proc_cell_info (user, cell_found, NAS_CELL_SELECTION_CNF (msg_p).tac, NAS_CELL_SELECTION_CNF (msg_p).cellID, NAS_CELL_SELECTION_CNF (msg_p).rat, NAS_CELL_SELECTION_CNF (msg_p).rsrq, NAS_CELL_SELECTION_CNF (msg_p).rsrp); } @@ -160,7 +211,7 @@ void *nas_ue_task(void *args_p) if ((NAS_CONN_ESTABLI_CNF (msg_p).errCode == AS_SUCCESS) || (NAS_CONN_ESTABLI_CNF (msg_p).errCode == AS_TERMINATED_NAS)) { - nas_proc_establish_cnf(NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.data, NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.length); + nas_proc_establish_cnf(user, NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.data, NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.length); /* TODO checks if NAS will free the nas message, better to do it there anyway! */ // result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data); @@ -173,7 +224,7 @@ void *nas_ue_task(void *args_p) LOG_I(NAS, "[UE %d] Received %s: cause %u\n", Mod_id, msg_name, NAS_CONN_RELEASE_IND (msg_p).cause); - nas_proc_release_ind (NAS_CONN_RELEASE_IND (msg_p).cause); + nas_proc_release_ind (user, NAS_CONN_RELEASE_IND (msg_p).cause); break; case NAS_UPLINK_DATA_CNF: @@ -181,9 +232,9 @@ void *nas_ue_task(void *args_p) NAS_UPLINK_DATA_CNF (msg_p).UEid, NAS_UPLINK_DATA_CNF (msg_p).errCode); if (NAS_UPLINK_DATA_CNF (msg_p).errCode == AS_SUCCESS) { - nas_proc_ul_transfer_cnf (); + nas_proc_ul_transfer_cnf (user); } else { - nas_proc_ul_transfer_rej (); + nas_proc_ul_transfer_rej (user); } break; @@ -192,7 +243,7 @@ void *nas_ue_task(void *args_p) LOG_I(NAS, "[UE %d] Received %s: UEid %u, length %u\n", Mod_id, msg_name, NAS_DOWNLINK_DATA_IND (msg_p).UEid, NAS_DOWNLINK_DATA_IND (msg_p).nasMsg.length); - nas_proc_dl_transfer_ind (NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length); + nas_proc_dl_transfer_ind (user, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length); if (0) { /* TODO checks if NAS will free the nas message, better to do it there anyway! */ @@ -215,10 +266,41 @@ void *nas_ue_task(void *args_p) nb_events = itti_get_events(TASK_NAS_UE, &events); if ((nb_events > 0) && (events != NULL)) { - if (nas_ue_process_events(events, nb_events) == TRUE) { + if (nas_ue_process_events(users, events, nb_events) == TRUE) { LOG_E(NAS, "[UE] Received exit loop\n"); } } } + + free(users); + return NULL; +} + +nas_user_t *find_user_from_fd(nas_user_container_t *users, int fd) { + for (int i=0; i<users->count; i++) { + nas_user_t *user = &users->item[i]; + if (fd == user_api_get_fd(user->user_api_id)) { + return user; + } + } + return NULL; +} + +char *make_port_str_from_ueid(const char *base_port_str, int ueid) { + int port; + int base_port; + char *endptr = NULL; + + base_port = strtol(base_port_str, &endptr, 10); + if ( base_port_str == endptr ) { + return NULL; + } + + port = base_port + ueid; + if ( port<1 || port > 65535 ) { + return NULL; + } + + return itoa(port); } #endif diff --git a/openair2/NAS/nas_ue_task.h b/openair3/NAS/UE/nas_ue_task.h similarity index 80% rename from openair2/NAS/nas_ue_task.h rename to openair3/NAS/UE/nas_ue_task.h index bc580726810cdf702db9f50435bb4dc09085b736..90ef26bd80ffbab5fdd6eac4d00938a8e4fcf706 100644 --- a/openair2/NAS/nas_ue_task.h +++ b/openair3/NAS/UE/nas_ue_task.h @@ -22,6 +22,17 @@ #ifndef NAS_UE_TASK_H_ #define NAS_UE_TASK_H_ +#include "openairinterface5g_limits.h" +#include "user_defs.h" + +// XXX simple array container for multiple users +typedef struct { + size_t count; + nas_user_t item[NUMBER_OF_UE_MAX]; +} nas_user_container_t; + +nas_user_t *find_user_from_fd(nas_user_container_t *users, int fd); + # if defined(ENABLE_ITTI) void *nas_ue_task(void *args_p); # endif diff --git a/openair3/NAS/UE/nas_user.c b/openair3/NAS/UE/nas_user.c index 7616a48c0528045c02730c3f0560e532cd370a4e..b698e4d682dc4923a26e3793d7f111aedc0cda49 100644 --- a/openair3/NAS/UE/nas_user.c +++ b/openair3/NAS/UE/nas_user.c @@ -37,8 +37,7 @@ Description NAS procedure functions triggered by the user *****************************************************************************/ -#include "nas_user.h" -#include "userDef.h" +#include "user_defs.h" #include "nas_log.h" #include "memory.h" @@ -47,6 +46,8 @@ Description NAS procedure functions triggered by the user #include "at_error.h" #include "user_indication.h" #include "nas_proc.h" +#include "nas_user.h" +#include "utils.h" #include "user_api.h" #include <string.h> // memset, strncpy, strncmp @@ -65,30 +66,30 @@ Description NAS procedure functions triggered by the user * Functions executed upon receiving AT command from the user * --------------------------------------------------------------------- */ -static int _nas_user_proc_cgsn (const at_command_t *data); -static int _nas_user_proc_cgmi (const at_command_t *data); -static int _nas_user_proc_cgmm (const at_command_t *data); -static int _nas_user_proc_cgmr (const at_command_t *data); -static int _nas_user_proc_cimi (const at_command_t *data); -static int _nas_user_proc_cfun (const at_command_t *data); -static int _nas_user_proc_cpin (const at_command_t *data); -static int _nas_user_proc_csq (const at_command_t *data); -static int _nas_user_proc_cesq (const at_command_t *data); -static int _nas_user_proc_cops (const at_command_t *data); -static int _nas_user_proc_cgatt (const at_command_t *data); -static int _nas_user_proc_creg (const at_command_t *data); -static int _nas_user_proc_cgreg (const at_command_t *data); -static int _nas_user_proc_cereg (const at_command_t *data); -static int _nas_user_proc_cgdcont (const at_command_t *data); -static int _nas_user_proc_cgact (const at_command_t *data); -static int _nas_user_proc_cmee (const at_command_t *data); -static int _nas_user_proc_clck (const at_command_t *data); -static int _nas_user_proc_cgpaddr (const at_command_t *data); -static int _nas_user_proc_cnum (const at_command_t *data); -static int _nas_user_proc_clac (const at_command_t *data); +static int _nas_user_proc_cgsn (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgmi (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgmm (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgmr (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cimi (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cfun (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cpin (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_csq (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cesq (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cops (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgatt (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_creg (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgreg (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cereg (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgdcont (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgact (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cmee (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_clck (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cgpaddr (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_cnum (nas_user_t *user, const at_command_t *data); +static int _nas_user_proc_clac (nas_user_t *user, const at_command_t *data); /* NAS procedures applicable to AT commands */ -typedef int (*_nas_user_procedure_t) (const at_command_t *); +typedef int (*_nas_user_procedure_t) (nas_user_t *, const at_command_t *); static _nas_user_procedure_t _nas_user_procedure[AT_COMMAND_ID_MAX] = { NULL, @@ -115,31 +116,12 @@ static _nas_user_procedure_t _nas_user_procedure[AT_COMMAND_ID_MAX] = { _nas_user_proc_cgpaddr, /* CGPADDR */ }; -/* - * Internal representation of data structure returned to the user - * as the result of NAS procedure function call - */ -static at_response_t _nas_user_data = {}; - /* * --------------------------------------------------------------------- * Local UE context * --------------------------------------------------------------------- */ -/* - * MT SIM pending status (see ETSI TS 127 007 V10.6.0, Note 2) - * Commands which interact with MT that are accepted when MT is pending SIM PIN, - * SIM PUK, or PH-SIM are: +CGMI, +CGMM, +CGMR, +CGSN, D112; (emergency call), - * +CPAS, +CFUN, +CPIN, +CPINR, +CDIS (read and test command only), and +CIND - * (read and test command only). -*/ -typedef enum { - NAS_USER_READY, /* MT is not pending for any password */ - NAS_USER_SIM_PIN, /* MT is waiting SIM PIN to be given */ - NAS_USER_SIM_PUK, /* MT is waiting SIM PUK to be given */ - NAS_USER_PH_SIM_PIN /* MT is waiting phone-to-SIM card - * password to be given */ -} nas_user_sim_status; + static const char *_nas_user_sim_status_str[] = { "READY", "SIM PIN", @@ -147,29 +129,16 @@ static const char *_nas_user_sim_status_str[] = { "PH-SIM PIN" }; -/* - * The local UE context - */ -static struct { - /* Firmware version number */ - const char *version; - /* SIM pending status */ - nas_user_sim_status sim_status; - /* Level of functionality */ - int fun; -} _nas_user_context; - -/* - * --------------------------------------------------------------------- - * UE parameters stored in the UE's non-volatile memory device - * --------------------------------------------------------------------- - */ -static user_nvdata_t _nas_user_nvdata; - /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ +void _nas_user_context_initialize(nas_user_context_t *nas_user_context, const char *version) { + nas_user_context->version = version; + nas_user_context->sim_status = NAS_USER_SIM_PIN; + nas_user_context->fun = AT_CFUN_FUN_DEFAULT; +} + /**************************************************************************** ** ** ** Name: nas_user_initialize() ** @@ -183,38 +152,27 @@ static user_nvdata_t _nas_user_nvdata; ** ** ** Outputs: None ** ** Return: None ** - ** Others: _nas_user_nvdata, _nas_user_context ** ** ** ***************************************************************************/ -void nas_user_initialize(emm_indication_callback_t emm_cb, +void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, esm_indication_callback_t esm_cb, const char *version) { LOG_FUNC_IN; - /* Get UE's data pathname */ - char *path = memory_get_path(USER_NVRAM_DIRNAME, USER_NVRAM_FILENAME); - - if (path == NULL) { - LOG_TRACE(ERROR, "USR-MAIN - Failed to get UE's data pathname"); - } + user->nas_user_nvdata = calloc_or_fail(sizeof(user_nvdata_t)); /* Get UE data stored in the non-volatile memory device */ - else { - int rc = memory_read(path, &_nas_user_nvdata, sizeof(user_nvdata_t)); - - if (rc != RETURNok) { - LOG_TRACE(ERROR, "USR-MAIN - Failed to read %s", path); - } - - free(path); + int rc = memory_read(user->user_nvdata_store, user->nas_user_nvdata, sizeof(user_nvdata_t)); + if (rc != RETURNok) { + LOG_TRACE(ERROR, "USR-MAIN - Failed to read non volatile memory"); + abort(); } - _nas_user_context.version = version; - _nas_user_context.sim_status = NAS_USER_SIM_PIN; - _nas_user_context.fun = AT_CFUN_FUN_DEFAULT; + user->nas_user_context = calloc_or_fail(sizeof(nas_user_context_t)); + _nas_user_context_initialize(user->nas_user_context, version); /* Initialize the internal NAS processing data */ - nas_proc_initialize(emm_cb, esm_cb, _nas_user_nvdata.IMEI); + nas_proc_initialize(user, emm_cb, esm_cb, user->nas_user_nvdata->IMEI); LOG_FUNC_OUT; } @@ -232,7 +190,7 @@ void nas_user_initialize(emm_indication_callback_t emm_cb, ** Outputs: Return: FALSE, TRUE ** ** ** ***************************************************************************/ -int nas_user_receive_and_process(int *fd, char *message) +int nas_user_receive_and_process(nas_user_t *user, char *message) { LOG_FUNC_IN; @@ -240,13 +198,14 @@ int nas_user_receive_and_process(int *fd, char *message) int nb_command; int bytes; int i; + user_api_id_t *user_api_id = user->user_api_id; if (message != NULL) { /* Set the message in receive buffer (Use to simulate reception of data from UserProcess) */ - bytes = user_api_set_data(message); + bytes = user_api_set_data(user_api_id, message); } else { /* Read the user data message */ - bytes = user_api_read_data (*fd); + bytes = user_api_read_data (user_api_id); if (bytes == RETURNerror) { /* Failed to read data from the user application layer; @@ -263,11 +222,11 @@ int nas_user_receive_and_process(int *fd, char *message) } /* Decode the user data message */ - nb_command = user_api_decode_data (bytes); + nb_command = user_api_decode_data (user_api_id, user->user_at_commands, bytes); for (i = 0; i < nb_command; i++) { /* Get the user data to be processed */ - const void *data = user_api_get_data (i); + const void *data = user_api_get_data (user->user_at_commands, i); if (data == NULL) { /* Failed to get user data at the given index; @@ -279,7 +238,7 @@ int nas_user_receive_and_process(int *fd, char *message) } /* Process the user data message */ - ret_code = nas_user_process_data (data); + ret_code = nas_user_process_data (user, data); if (ret_code != RETURNok) { /* The user data message has not been successfully @@ -293,7 +252,7 @@ int nas_user_receive_and_process(int *fd, char *message) /* Send response to UserProcess (If not in simulated reception) */ if (message == NULL) { /* Encode the user data message */ - bytes = user_api_encode_data (nas_user_get_data (), i == nb_command - 1); + bytes = user_api_encode_data (user->user_api_id, nas_user_get_data (user), i == nb_command - 1); if (bytes == RETURNerror) { /* Failed to encode the user data message; @@ -302,7 +261,7 @@ int nas_user_receive_and_process(int *fd, char *message) } /* Send the data message to the user */ - bytes = user_api_send_data (*fd, bytes); + bytes = user_api_send_data (user_api_id, bytes); if (bytes == RETURNerror) { /* Failed to send data to the user application layer; @@ -331,12 +290,12 @@ int nas_user_receive_and_process(int *fd, char *message) ** Outputs: None ** ** Return: RETURNok if the command has been success- ** ** fully executed; RETURNerror otherwise ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -int nas_user_process_data(const void *data) +int nas_user_process_data(nas_user_t *user, const void *data) { LOG_FUNC_IN; + at_response_t *at_response = user->at_response; int ret_code = RETURNerror; @@ -355,18 +314,18 @@ int nas_user_process_data(const void *data) nas_procedure = _nas_user_procedure[user_data->id]; if (nas_procedure != NULL) { - ret_code = (*nas_procedure)(user_data); + ret_code = (*nas_procedure)(user, user_data); } else { /* AT command related to result format only */ - _nas_user_data.id = user_data->id; - _nas_user_data.type = user_data->type; - _nas_user_data.mask = user_data->mask; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = user_data->id; + at_response->type = user_data->type; + at_response->mask = user_data->mask; + at_response->cause_code = AT_ERROR_SUCCESS; ret_code = RETURNok; } } else { LOG_TRACE(ERROR, "USR-MAIN - Data to be processed is null"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } LOG_FUNC_RETURN (ret_code); @@ -389,10 +348,10 @@ int nas_user_process_data(const void *data) ** Others: None ** ** ** ***************************************************************************/ -const void *nas_user_get_data(void) +const void *nas_user_get_data(nas_user_t *user) { LOG_FUNC_IN; - LOG_FUNC_RETURN ((void *) &_nas_user_data); + LOG_FUNC_RETURN ((void *) user->at_response); } /****************************************************************************/ @@ -411,30 +370,29 @@ const void *nas_user_get_data(void) ** ning the IMEI. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_nvdata ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgsn(const at_command_t *data) +static int _nas_user_proc_cgsn(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgsn_resp_t *cgsn = &_nas_user_data.response.cgsn; + at_cgsn_resp_t *cgsn = &at_response->response.cgsn; memset(cgsn, 0, sizeof(at_cgsn_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGSN_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGSN_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: /* Get the Product Serial Number Identification (IMEI) */ - strncpy(cgsn->sn, _nas_user_nvdata.IMEI, + strncpy(cgsn->sn, user->nas_user_nvdata->IMEI, AT_RESPONSE_INFO_TEXT_SIZE); break; @@ -445,7 +403,7 @@ static int _nas_user_proc_cgsn(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGSN command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -463,30 +421,29 @@ static int _nas_user_proc_cgsn(const at_command_t *data) ** le Equipment to which it is connected to. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_nvdata ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgmi(const at_command_t *data) +static int _nas_user_proc_cgmi(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgmi_resp_t *cgmi = &_nas_user_data.response.cgmi; + at_cgmi_resp_t *cgmi = &at_response->response.cgmi; memset(cgmi, 0, sizeof(at_cgmi_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGMI_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGMI_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: /* Get the Manufacturer identifier */ - strncpy(cgmi->manufacturer, _nas_user_nvdata.manufacturer, + strncpy(cgmi->manufacturer, user->nas_user_nvdata->manufacturer, AT_RESPONSE_INFO_TEXT_SIZE); break; @@ -497,7 +454,7 @@ static int _nas_user_proc_cgmi(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGMI command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -515,30 +472,29 @@ static int _nas_user_proc_cgmi(const at_command_t *data) ** Equipment to which it is connected to. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_nvdata ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgmm(const at_command_t *data) +static int _nas_user_proc_cgmm(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgmm_resp_t *cgmm = &_nas_user_data.response.cgmm; + at_cgmm_resp_t *cgmm = &at_response->response.cgmm; memset(cgmm, 0, sizeof(at_cgmm_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGMM_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGMM_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: /* Get the Model identifier */ - strncpy(cgmm->model, _nas_user_nvdata.model, + strncpy(cgmm->model, user->nas_user_nvdata->model, AT_RESPONSE_INFO_TEXT_SIZE); break; @@ -549,7 +505,7 @@ static int _nas_user_proc_cgmm(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGMM command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -568,30 +524,30 @@ static int _nas_user_proc_cgmm(const at_command_t *data) ** Equipment to which it is connected to. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgmr(const at_command_t *data) +static int _nas_user_proc_cgmr(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgmr_resp_t *cgmr = &_nas_user_data.response.cgmr; + at_cgmr_resp_t *cgmr = &at_response->response.cgmr; memset(cgmr, 0, sizeof(at_cgmr_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGMR_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGMR_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: /* Get the revision identifier */ - strncpy(cgmr->revision, _nas_user_context.version, + strncpy(cgmr->revision, nas_user_context->version, AT_RESPONSE_INFO_TEXT_SIZE); break; @@ -602,7 +558,7 @@ static int _nas_user_proc_cgmr(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGMR command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -624,39 +580,39 @@ static int _nas_user_proc_cgmr(const at_command_t *data) ** ning the IMSI. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_nvdata ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cimi(const at_command_t *data) +static int _nas_user_proc_cimi(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cimi_resp_t *cimi = &_nas_user_data.response.cimi; + at_cimi_resp_t *cimi = &at_response->response.cimi; memset(cimi, 0, sizeof(at_cimi_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CIMI_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CIMI_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } /* Get the International Mobile Subscriber Identity (IMSI) */ - ret_code = nas_proc_get_imsi(cimi->IMSI); + ret_code = nas_proc_get_imsi(user->emm_data, cimi->IMSI); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get IMSI number"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -668,7 +624,7 @@ static int _nas_user_proc_cimi(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CIMI command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -685,27 +641,27 @@ static int _nas_user_proc_cimi(const at_command_t *data) ** to different power consumption states. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cfun(const at_command_t *data) +static int _nas_user_proc_cfun(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cfun_resp_t *cfun = &_nas_user_data.response.cfun; + at_cfun_resp_t *cfun = &at_response->response.cfun; memset(cfun, 0, sizeof(at_cfun_resp_t)); int fun = AT_CFUN_FUN_DEFAULT; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CFUN_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CFUN_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: @@ -721,7 +677,7 @@ static int _nas_user_proc_cfun(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <rst> parameter is not valid" " (%d)", data->command.cfun.rst); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -734,7 +690,7 @@ static int _nas_user_proc_cfun(const at_command_t *data) * is not valid; return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <fun> parameter is not valid" " (%d)", data->command.cfun.fun); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -751,7 +707,7 @@ static int _nas_user_proc_cfun(const at_command_t *data) case AT_CFUN_FULL: /* Notify the NAS procedure call manager that the UE is * operational */ - ret_code = nas_proc_enable_s1_mode(); + ret_code = nas_proc_enable_s1_mode(user); break; default: @@ -761,14 +717,14 @@ static int _nas_user_proc_cfun(const at_command_t *data) if (ret_code != RETURNerror) { /* Update the functionality level */ - _nas_user_context.fun = fun; + nas_user_context->fun = fun; } break; case AT_COMMAND_GET: /* Get the MT's functionality level */ - cfun->fun = _nas_user_context.fun; + cfun->fun = nas_user_context->fun; break; case AT_COMMAND_TST: @@ -780,7 +736,7 @@ static int _nas_user_proc_cfun(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CFUN command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -798,25 +754,25 @@ static int _nas_user_proc_cfun(const at_command_t *data) ** can be operated. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_context, _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cpin(const at_command_t *data) +static int _nas_user_proc_cpin(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cpin_resp_t *cpin = &_nas_user_data.response.cpin; + at_cpin_resp_t *cpin = &at_response->response.cpin; memset(cpin, 0, sizeof(at_cpin_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CPIN_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CPIN_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: @@ -825,24 +781,24 @@ static int _nas_user_proc_cpin(const at_command_t *data) * Set command sends to the MT a password which is necessary * before it can be operated */ - if (_nas_user_context.sim_status == NAS_USER_SIM_PIN) { + if (nas_user_context->sim_status == NAS_USER_SIM_PIN) { /* The MT is waiting for PIN password; check the PIN code */ - if (strncmp(_nas_user_nvdata.PIN, + if (strncmp(user->nas_user_nvdata->PIN, data->command.cpin.pin, USER_PIN_SIZE) != 0) { /* The PIN code is NOT matching; return an error message */ LOG_TRACE(ERROR, "USR-MAIN - PIN code is not correct " "(%s)", data->command.cpin.pin); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PASSWD; + at_response->cause_code = AT_ERROR_INCORRECT_PASSWD; ret_code = RETURNerror; } else { /* The PIN code is matching; update the user's PIN * pending status */ - _nas_user_context.sim_status = NAS_USER_READY; + nas_user_context->sim_status = NAS_USER_READY; } } else { /* The MT is NOT waiting for PIN password; * return an error message */ - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_ALLOWED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_ALLOWED; ret_code = RETURNerror; } @@ -854,7 +810,7 @@ static int _nas_user_proc_cpin(const at_command_t *data) * whether some password is required or not. */ strncpy(cpin->code, - _nas_user_sim_status_str[_nas_user_context.sim_status], + _nas_user_sim_status_str[nas_user_context->sim_status], AT_CPIN_RESP_SIZE); break; @@ -866,7 +822,7 @@ static int _nas_user_proc_cpin(const at_command_t *data) /* Other types of AT CPIN command are not valid */ LOG_TRACE(ERROR, "USR-MAIN - AT+CPIN command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -884,30 +840,30 @@ static int _nas_user_proc_cpin(const at_command_t *data) ** Equipment. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_csq(const at_command_t *data) +static int _nas_user_proc_csq(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_csq_resp_t *csq = &_nas_user_data.response.csq; + at_csq_resp_t *csq = &at_response->response.csq; memset(csq, 0, sizeof(at_csq_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CSQ_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CSQ_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -928,7 +884,7 @@ static int _nas_user_proc_csq(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CSQ command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -945,30 +901,30 @@ static int _nas_user_proc_csq(const at_command_t *data) ** meters. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cesq(const at_command_t *data) +static int _nas_user_proc_cesq(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cesq_resp_t *cesq = &_nas_user_data.response.cesq; + at_cesq_resp_t *cesq = &at_response->response.cesq; memset(cesq, 0, sizeof(at_cesq_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CESQ_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CESQ_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -979,7 +935,7 @@ static int _nas_user_proc_cesq(const at_command_t *data) cesq->ber = AT_CESQ_BER_UNKNOWN; cesq->rscp = AT_CESQ_RSCP_UNKNOWN; cesq->ecno = AT_CESQ_ECNO_UNKNOWN; - ret_code = nas_proc_get_signal_quality(&cesq->rsrq, &cesq->rsrp); + ret_code = nas_proc_get_signal_quality(user, &cesq->rsrq, &cesq->rsrp); break; case AT_COMMAND_TST: @@ -991,7 +947,7 @@ static int _nas_user_proc_cesq(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CESQ command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1010,19 +966,19 @@ static int _nas_user_proc_cesq(const at_command_t *data) ** slot. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cops(const at_command_t *data) +static int _nas_user_proc_cops(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cops_resp_t *cops = &_nas_user_data.response.cops; + at_cops_resp_t *cops = &at_response->response.cops; memset(cops, 0, sizeof(at_cops_resp_t)); static int read_format = AT_COPS_FORMAT_DEFAULT; @@ -1035,15 +991,15 @@ static int _nas_user_proc_cops(const at_command_t *data) int oper_is_selected; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_NO_PARAM; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_NO_PARAM; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -1079,7 +1035,7 @@ static int _nas_user_proc_cops(const at_command_t *data) /* <oper> field shall be present */ if ( !(data->mask & AT_COPS_OPER_MASK) ) { LOG_TRACE(ERROR, "USR-MAIN - <oper> parameter is not present"); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1087,7 +1043,7 @@ static int _nas_user_proc_cops(const at_command_t *data) /* <format> field shall be present */ if ( !(data->mask & AT_COPS_FORMAT_MASK) ) { LOG_TRACE(ERROR, "USR-MAIN - <format> parameter is not present"); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1098,7 +1054,7 @@ static int _nas_user_proc_cops(const at_command_t *data) /* The value of <format> field is not valid */ LOG_TRACE(ERROR, "USR-MAIN - <format> parameter is not valid (%d)", data->command.cops.format); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1112,7 +1068,7 @@ static int _nas_user_proc_cops(const at_command_t *data) /* The value of <AcT> field is not valid */ LOG_TRACE(ERROR, "USR-MAIN - <AcT> parameter is not valid (%d)", data->command.cops.AcT); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1140,7 +1096,7 @@ static int _nas_user_proc_cops(const at_command_t *data) /* The value of <format> field is not valid */ LOG_TRACE(ERROR, "USR-MAIN - <format> parameter is not valid (%d)", data->command.cops.format); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1156,7 +1112,7 @@ static int _nas_user_proc_cops(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - <mode> parameter is not supported (%d)", mode); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1168,22 +1124,22 @@ static int _nas_user_proc_cops(const at_command_t *data) if (ret_code != RETURNerror) { if (mode == AT_COPS_DEREG) { /* Force an attempt to deregister from the network */ - ret_code = nas_proc_deregister(); + ret_code = nas_proc_deregister(user); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Network deregistration failed"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; break; } } else if (mode != AT_COPS_FORMAT) { /* Force an attempt to automatically/manualy select * and register the GSM/UMTS/EPS network operator */ - ret_code = nas_proc_register(mode, format, + ret_code = nas_proc_register(user, mode, format, &data->command.cops.plmn, AcT); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Network registration failed (<mode>=%d)", mode); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; break; } } @@ -1198,14 +1154,14 @@ static int _nas_user_proc_cops(const at_command_t *data) */ /* Get the current network registration data */ - ret_code = nas_proc_get_reg_data(&mode, + ret_code = nas_proc_get_reg_data(user, &mode, &oper_is_selected, read_format, &cops->get.plmn, &cops->get.AcT); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get registration data (<mode>=%d)", mode); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; break; } @@ -1221,11 +1177,11 @@ static int _nas_user_proc_cops(const at_command_t *data) /* Set optional parameter bitmask */ if (oper_is_selected) { cops->get.format = read_format; - _nas_user_data.mask |= (AT_COPS_RESP_FORMAT_MASK | + at_response->mask |= (AT_COPS_RESP_FORMAT_MASK | AT_COPS_RESP_OPER_MASK); if (cops->get.AcT != NET_ACCESS_UNAVAILABLE) { - _nas_user_data.mask |= AT_COPS_RESP_ACT_MASK; + at_response->mask |= AT_COPS_RESP_ACT_MASK; } } @@ -1236,13 +1192,13 @@ static int _nas_user_proc_cops(const at_command_t *data) * Test command returns a set of parameters, each representing * an operator present in the network. */ - cops->tst.size = nas_proc_get_oper_list(&cops->tst.data); + cops->tst.size = nas_proc_get_oper_list(user, &cops->tst.data); break; default: LOG_TRACE(ERROR, "USR-MAIN - AT+COPS command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1259,30 +1215,30 @@ static int _nas_user_proc_cops(const at_command_t *data) ** or detach the MT from, the EPS service. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgatt(const at_command_t *data) +static int _nas_user_proc_cgatt(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgatt_resp_t *cgatt = &_nas_user_data.response.cgatt; + at_cgatt_resp_t *cgatt = &at_response->response.cgatt; memset(cgatt, 0, sizeof(at_cgatt_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGATT_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGATT_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -1297,7 +1253,7 @@ static int _nas_user_proc_cgatt(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <state> parameter is not valid (%d)", data->command.cgatt.state); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1308,16 +1264,16 @@ static int _nas_user_proc_cgatt(const at_command_t *data) ret_code = RETURNerror; if (data->command.cgatt.state == AT_CGATT_ATTACHED) { - ret_code = nas_proc_attach(); + ret_code = nas_proc_attach(user); } else if (data->command.cgatt.state == AT_CGATT_DETACHED) { - ret_code = nas_proc_detach(FALSE); + ret_code = nas_proc_detach(user, FALSE); } if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to attach/detach " "to/from EPS service (<state>=%d)", data->command.cgatt.state); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } } @@ -1328,7 +1284,7 @@ static int _nas_user_proc_cgatt(const at_command_t *data) /* * Read command returns the current EPS service state. */ - if (nas_proc_get_attach_status() != TRUE) { + if (nas_proc_get_attach_status(user) != TRUE) { cgatt->state = AT_CGATT_DETACHED; } else { cgatt->state = AT_CGATT_ATTACHED; @@ -1346,7 +1302,7 @@ static int _nas_user_proc_cgatt(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGATT command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1364,32 +1320,32 @@ static int _nas_user_proc_cgatt(const at_command_t *data) ** location information in GERA/UTRA/E-UTRA Network. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_creg(const at_command_t *data) +static int _nas_user_proc_creg(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_creg_resp_t *creg = &_nas_user_data.response.creg; + at_creg_resp_t *creg = &at_response->response.creg; memset(creg, 0, sizeof(at_creg_resp_t)); static int n = AT_CREG_N_DEFAULT; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_NO_PARAM; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_NO_PARAM; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -1406,7 +1362,7 @@ static int _nas_user_proc_creg(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <n> parameter is not valid" " (%d)", data->command.creg.n); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1432,7 +1388,7 @@ static int _nas_user_proc_creg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to disable logging of network notification"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1447,7 +1403,7 @@ static int _nas_user_proc_creg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to enable logging of registration status"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1474,11 +1430,11 @@ static int _nas_user_proc_creg(const at_command_t *data) case AT_CREG_OFF: case AT_CREG_ON: /* Get network registration status */ - ret_code = nas_proc_get_reg_status(&creg->stat); + ret_code = nas_proc_get_reg_status(user, &creg->stat); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get registration status"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1495,7 +1451,7 @@ static int _nas_user_proc_creg(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CREG command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1513,32 +1469,32 @@ static int _nas_user_proc_creg(const at_command_t *data) ** information in GERA/UTRA Network. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgreg(const at_command_t *data) +static int _nas_user_proc_cgreg(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgreg_resp_t *cgreg = &_nas_user_data.response.cgreg; + at_cgreg_resp_t *cgreg = &at_response->response.cgreg; memset(cgreg, 0, sizeof(at_cgreg_resp_t)); static int n = AT_CGREG_N_DEFAULT; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_NO_PARAM; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_NO_PARAM; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -1555,7 +1511,7 @@ static int _nas_user_proc_cgreg(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <n> parameter is not valid" " (%d)", data->command.cgreg.n); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1581,7 +1537,7 @@ static int _nas_user_proc_cgreg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to disable logging of network notification"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1596,7 +1552,7 @@ static int _nas_user_proc_cgreg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to enable logging of registration status"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1623,11 +1579,11 @@ static int _nas_user_proc_cgreg(const at_command_t *data) case AT_CGREG_OFF: case AT_CGREG_ON: /* Get network registration status */ - ret_code = nas_proc_get_reg_status(&cgreg->stat); + ret_code = nas_proc_get_reg_status(user, &cgreg->stat); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get registration status"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1644,7 +1600,7 @@ static int _nas_user_proc_cgreg(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGREG command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1662,32 +1618,32 @@ static int _nas_user_proc_cgreg(const at_command_t *data) ** information in E-UTRA Network. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cereg(const at_command_t *data) +static int _nas_user_proc_cereg(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cereg_resp_t *cereg = &_nas_user_data.response.cereg; + at_cereg_resp_t *cereg = &at_response->response.cereg; memset(cereg, 0, sizeof(at_cereg_resp_t)); static int n = AT_CEREG_N_DEFAULT; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_NO_PARAM; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_NO_PARAM; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -1704,7 +1660,7 @@ static int _nas_user_proc_cereg(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <n> parameter is not valid" " (%d)", data->command.cereg.n); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1730,7 +1686,7 @@ static int _nas_user_proc_cereg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to disable logging of network notification"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1741,7 +1697,7 @@ static int _nas_user_proc_cereg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to enable logging of location information"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1753,7 +1709,7 @@ static int _nas_user_proc_cereg(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to enable logging of registration status"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1776,21 +1732,21 @@ static int _nas_user_proc_cereg(const at_command_t *data) switch (n) { case AT_CEREG_BOTH: /* Get EPS location information */ - ret_code = nas_proc_get_loc_info(cereg->tac, cereg->ci, + ret_code = nas_proc_get_loc_info(user, cereg->tac, cereg->ci, &cereg->AcT); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get location information"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; break; } if (cereg->tac[0] != 0) { - _nas_user_data.mask |= (AT_CEREG_RESP_TAC_MASK | + at_response->mask |= (AT_CEREG_RESP_TAC_MASK | AT_CEREG_RESP_CI_MASK); if (cereg->AcT != NET_ACCESS_UNAVAILABLE) { - _nas_user_data.mask |= (AT_CEREG_RESP_ACT_MASK); + at_response->mask |= (AT_CEREG_RESP_ACT_MASK); } } @@ -1799,11 +1755,11 @@ static int _nas_user_proc_cereg(const at_command_t *data) case AT_CEREG_OFF: case AT_CEREG_ON: /* Get network registration status */ - ret_code = nas_proc_get_reg_status(&cereg->stat); + ret_code = nas_proc_get_reg_status(user, &cereg->stat); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get registration status"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -1820,7 +1776,7 @@ static int _nas_user_proc_cereg(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CEREG command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -1843,19 +1799,19 @@ static int _nas_user_proc_cereg(const at_command_t *data) ** fault bearer and traffic flows in EPS. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgdcont(const at_command_t *data) +static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgdcont_get_t *cgdcont = &_nas_user_data.response.cgdcont.get; + at_cgdcont_get_t *cgdcont = &at_response->response.cgdcont.get; memset(cgdcont, 0, sizeof(at_cgdcont_resp_t)); int cid = AT_CGDCONT_CID_DEFAULT; @@ -1867,15 +1823,15 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) int im_cn_signalling = AT_CGDCONT_IM_CM_DEFAULT; int reset_pdn = TRUE; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_NO_PARAM; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_NO_PARAM; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -1889,7 +1845,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <cid> parameter is not valid" " (%d)", data->command.cgdcont.cid); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1909,7 +1865,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <PDN_type> parameter is not " "valid (%s)", data->command.cgdcont.PDP_type); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1928,7 +1884,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) * not valid; return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <d_comp> parameter is not " "valid (%d)", data->command.cgdcont.d_comp); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1943,7 +1899,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) * not valid; return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <h_comp> parameter is not " "valid (%d)", data->command.cgdcont.h_comp); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1959,7 +1915,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) LOG_TRACE(ERROR, "USR-MAIN - <IPv4AddrAlloc> parameter " "is not valid (%d)", data->command.cgdcont.IPv4AddrAlloc); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1975,7 +1931,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) LOG_TRACE(ERROR, "USR-MAIN - <emergency indication> " "parameter is not valid (%d)", data->command.cgdcont.emergency_indication); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -1991,7 +1947,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) LOG_TRACE(ERROR, "USR-MAIN - <P-CSCF_discovery> " "parameter is not valid (%d)", data->command.cgdcont.P_CSCF_discovery); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2008,7 +1964,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) LOG_TRACE(ERROR, "USR-MAIN - <IM_CN_Signalling_Flag_Ind> " "parameter is not valid (%d)", data->command.cgdcont.IM_CN_Signalling_Flag_Ind); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2022,10 +1978,10 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) if (reset_pdn) { /* A special form of the set command, +CGDCONT=<cid> causes * the values for context number <cid> to become undefined */ - ret_code = nas_proc_reset_pdn(cid); + ret_code = nas_proc_reset_pdn(user, cid); } else { /* Define a new PDN connection */ - ret_code = nas_proc_set_pdn(cid, pdn_type, apn, + ret_code = nas_proc_set_pdn(user, cid, pdn_type, apn, ipv4_addr_allocation, emergency, p_cscf, im_cn_signalling); } @@ -2033,7 +1989,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to setup PDN connection " "(<cid>=%d)", data->command.cgdcont.cid); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2043,14 +1999,14 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) * Read command returns the current settings for each * defined PDN connection/default EPS bearer context */ - cgdcont->n_pdns = nas_proc_get_pdn_param(cgdcont->cid, + cgdcont->n_pdns = nas_proc_get_pdn_param(user->esm_data, cgdcont->cid, cgdcont->PDP_type, cgdcont->APN, AT_CGDCONT_RESP_SIZE); if (cgdcont->n_pdns == 0) { LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2061,15 +2017,15 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) */ { /* Get the maximum value of a PDN context identifier */ - int cid_max = nas_proc_get_pdn_range(); + int cid_max = nas_proc_get_pdn_range(user->esm_data); if (cid_max > AT_CGDCONT_RESP_SIZE) { /* The range is defined by the user interface */ - _nas_user_data.response.cgdcont.tst.n_cid = + at_response->response.cgdcont.tst.n_cid = AT_CGDCONT_RESP_SIZE; } else { /* The range is defined by the ESM sublayer application */ - _nas_user_data.response.cgdcont.tst.n_cid = cid_max; + at_response->response.cgdcont.tst.n_cid = cid_max; } } break; @@ -2077,7 +2033,7 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGDCONT command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -2095,33 +2051,33 @@ static int _nas_user_proc_cgdcont(const at_command_t *data) ** for E-UTRAN ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgact(const at_command_t *data) +static int _nas_user_proc_cgact(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgact_resp_t *cgact = &_nas_user_data.response.cgact; + at_cgact_resp_t *cgact = &at_response->response.cgact; memset(cgact, 0, sizeof(at_cgact_resp_t)); int cid = -1; int state = AT_CGACT_STATE_DEFAULT; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGACT_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGACT_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -2136,7 +2092,7 @@ static int _nas_user_proc_cgact(const at_command_t *data) * not valid; return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <state> parameter is " "not valid (%d)", data->command.cgact.state); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2150,7 +2106,7 @@ static int _nas_user_proc_cgact(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <cid> parameter is " "not valid (%d)", data->command.cgact.cid); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2164,9 +2120,9 @@ static int _nas_user_proc_cgact(const at_command_t *data) ret_code = RETURNerror; if (state == AT_CGACT_DEACTIVATED) { - ret_code = nas_proc_deactivate_pdn(cid); + ret_code = nas_proc_deactivate_pdn(user, cid); } else if (state == AT_CGACT_ACTIVATED) { - ret_code = nas_proc_activate_pdn(cid); + ret_code = nas_proc_activate_pdn(user, cid); } if (ret_code != RETURNok) { @@ -2174,7 +2130,7 @@ static int _nas_user_proc_cgact(const at_command_t *data) "(<state>=%d,<cid>=%d)", (state != AT_CGACT_ACTIVATED)? "deactivate" : "activate", state, cid); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2184,12 +2140,12 @@ static int _nas_user_proc_cgact(const at_command_t *data) * The read command returns the current activation states for * all the defined PDN/EPS bearer contexts */ - cgact->n_pdns = nas_proc_get_pdn_status(cgact->cid, cgact->state, + cgact->n_pdns = nas_proc_get_pdn_status(user, cgact->cid, cgact->state, AT_CGACT_RESP_SIZE); if (cgact->n_pdns == 0) { LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2204,7 +2160,7 @@ static int _nas_user_proc_cgact(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGACT command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -2226,23 +2182,23 @@ static int _nas_user_proc_cgact(const at_command_t *data) ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cmee(const at_command_t *data) +static int _nas_user_proc_cmee(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; int ret_code = RETURNok; - at_cmee_resp_t *cmee = &_nas_user_data.response.cmee; + at_response_t *at_response = user->at_response; + at_cmee_resp_t *cmee = &at_response->response.cmee; memset(cmee, 0, sizeof(at_cmee_resp_t)); int n = AT_CMEE_N_DEFAULT; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CMEE_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CMEE_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: /* ATV0, ATV1 response format commands */ @@ -2260,7 +2216,7 @@ static int _nas_user_proc_cmee(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <n> parameter is not valid" " (%d)", data->command.cmee.n); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2304,7 +2260,7 @@ static int _nas_user_proc_cmee(const at_command_t *data) if (cmee->n == RETURNerror) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get format of the final result code"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2318,7 +2274,7 @@ static int _nas_user_proc_cmee(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CMEE command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -2339,21 +2295,21 @@ static int _nas_user_proc_cmee(const at_command_t *data) ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_clck(const at_command_t *data) +static int _nas_user_proc_clck(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_clck_resp_t *clck = &_nas_user_data.response.clck; + at_clck_resp_t *clck = &at_response->response.clck; memset(clck, 0, sizeof(at_clck_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CLCK_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CLCK_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: @@ -2369,7 +2325,7 @@ static int _nas_user_proc_clck(const at_command_t *data) /* Facilities other than SIM is not supported */ LOG_TRACE(ERROR, "USR-MAIN - Facility is not supported (%s)", data->command.clck.fac); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2377,12 +2333,12 @@ static int _nas_user_proc_clck(const at_command_t *data) /* Check password parameter */ if (data->mask & AT_CLCK_PASSWD_MASK) { /* Check the PIN code */ - if (strncmp(_nas_user_nvdata.PIN, + if (strncmp(user->nas_user_nvdata->PIN, data->command.clck.passwd, USER_PIN_SIZE) != 0) { /* The PIN code is NOT matching; return an error message */ LOG_TRACE(ERROR, "USR-MAIN - Password is not correct " "(%s)", data->command.clck.passwd); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PASSWD; + at_response->cause_code = AT_ERROR_INCORRECT_PASSWD; ret_code = RETURNerror; break; } @@ -2397,14 +2353,14 @@ static int _nas_user_proc_clck(const at_command_t *data) /* unlock requires password */ LOG_TRACE(ERROR, "USR-MAIN - unlock mode of operation " "requires a password"); - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; ret_code = RETURNerror; break; } LOG_TRACE(ERROR, "USR-MAIN - unlock mode of operation " "is not supported"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; @@ -2415,14 +2371,14 @@ static int _nas_user_proc_clck(const at_command_t *data) /* unlock requires password */ LOG_TRACE(ERROR, "USR-MAIN - lock mode of operation " "requires a password"); - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; ret_code = RETURNerror; break; } LOG_TRACE(ERROR, "USR-MAIN - lock mode of operation " "is not supported"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; @@ -2434,7 +2390,7 @@ static int _nas_user_proc_clck(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - <mode> parameter is not valid" " (%d)", data->command.clck.mode); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2450,7 +2406,7 @@ static int _nas_user_proc_clck(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CLCK command type %d is not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -2467,32 +2423,32 @@ static int _nas_user_proc_clck(const at_command_t *data) ** for the specified context identifiers ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cgpaddr(const at_command_t *data) +static int _nas_user_proc_cgpaddr(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cgpaddr_resp_t *cgpaddr = &_nas_user_data.response.cgpaddr; + at_cgpaddr_resp_t *cgpaddr = &at_response->response.cgpaddr; memset(cgpaddr, 0, sizeof(at_cgpaddr_resp_t)); int cid = -1; - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CGPADDR_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CGPADDR_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_SET: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } @@ -2506,7 +2462,7 @@ static int _nas_user_proc_cgpaddr(const at_command_t *data) * return an error message */ LOG_TRACE(ERROR, "USR-MAIN - <cid> parameter is " "not valid (%d)", data->command.cgpaddr.cid); - _nas_user_data.cause_code = AT_ERROR_INCORRECT_PARAMETERS; + at_response->cause_code = AT_ERROR_INCORRECT_PARAMETERS; ret_code = RETURNerror; break; } @@ -2517,14 +2473,14 @@ static int _nas_user_proc_cgpaddr(const at_command_t *data) /* * Get the PDP addresses */ - cgpaddr->n_pdns = nas_proc_get_pdn_addr(cid, cgpaddr->cid, + cgpaddr->n_pdns = nas_proc_get_pdn_addr(user, cid, cgpaddr->cid, cgpaddr->PDP_addr_1, cgpaddr->PDP_addr_2, AT_CGPADDR_RESP_SIZE); if (cgpaddr->n_pdns == 0) { LOG_TRACE(ERROR, "USR-MAIN - No any PDN context is defined"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2533,7 +2489,7 @@ static int _nas_user_proc_cgpaddr(const at_command_t *data) /* * The test command returns a list of defined <cid>s. */ - cgpaddr->n_pdns = nas_proc_get_pdn_addr(cid, cgpaddr->cid, + cgpaddr->n_pdns = nas_proc_get_pdn_addr(user, cid, cgpaddr->cid, cgpaddr->PDP_addr_1, cgpaddr->PDP_addr_2, AT_CGPADDR_RESP_SIZE); @@ -2542,7 +2498,7 @@ static int _nas_user_proc_cgpaddr(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CGPADDR command type %d is " "not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -2559,39 +2515,39 @@ static int _nas_user_proc_cgpaddr(const at_command_t *data) ** subscriber. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_cnum(const at_command_t *data) +static int _nas_user_proc_cnum(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; + nas_user_context_t *nas_user_context = user->nas_user_context; + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_cnum_resp_t *cnum = &_nas_user_data.response.cnum; + at_cnum_resp_t *cnum = &at_response->response.cnum; memset(cnum, 0, sizeof(at_cnum_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CNUM_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CNUM_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: - if (_nas_user_context.sim_status != NAS_USER_READY) { - _nas_user_data.cause_code = AT_ERROR_SIM_PIN_REQUIRED; + if (nas_user_context->sim_status != NAS_USER_READY) { + at_response->cause_code = AT_ERROR_SIM_PIN_REQUIRED; LOG_FUNC_RETURN(RETURNerror); } /* Get the International Mobile Subscriber Identity (IMSI) */ - ret_code = nas_proc_get_msisdn(cnum->number, &cnum->type); + ret_code = nas_proc_get_msisdn(user, cnum->number, &cnum->type); if (ret_code != RETURNok) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get MS dialing number"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2603,7 +2559,7 @@ static int _nas_user_proc_cnum(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CNUM command type %d is " "not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } @@ -2620,25 +2576,23 @@ static int _nas_user_proc_cnum(const at_command_t *data) ** are available for the user. ** ** ** ** Inputs: data: Pointer to the AT command data structure ** - ** Others: _nas_user_context ** ** ** ** Outputs: None ** ** Return: RETURNok; RETURNerror; ** - ** Others: _nas_user_data ** ** ** ***************************************************************************/ -static int _nas_user_proc_clac(const at_command_t *data) +static int _nas_user_proc_clac(nas_user_t *user, const at_command_t *data) { LOG_FUNC_IN; - + at_response_t *at_response = user->at_response; int ret_code = RETURNok; - at_clac_resp_t *clac = &_nas_user_data.response.clac; + at_clac_resp_t *clac = &at_response->response.clac; memset(clac, 0, sizeof(at_clac_resp_t)); - _nas_user_data.id = data->id; - _nas_user_data.type = data->type; - _nas_user_data.mask = AT_RESPONSE_CLAC_MASK; - _nas_user_data.cause_code = AT_ERROR_SUCCESS; + at_response->id = data->id; + at_response->type = data->type; + at_response->mask = AT_RESPONSE_CLAC_MASK; + at_response->cause_code = AT_ERROR_SUCCESS; switch (data->type) { case AT_COMMAND_ACT: @@ -2648,7 +2602,7 @@ static int _nas_user_proc_clac(const at_command_t *data) if (clac->n_acs == 0) { LOG_TRACE(ERROR, "USR-MAIN - Failed to get the list of " "supported AT commands"); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; } break; @@ -2660,7 +2614,7 @@ static int _nas_user_proc_clac(const at_command_t *data) default: LOG_TRACE(ERROR, "USR-MAIN - AT+CLAC command type %d is " "not supported", data->type); - _nas_user_data.cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; + at_response->cause_code = AT_ERROR_OPERATION_NOT_SUPPORTED; ret_code = RETURNerror; break; } diff --git a/openair3/NAS/UE/nas_user.h b/openair3/NAS/UE/nas_user.h index 93b1cc8961bb574581f13fc3289d541478a95cbb..eb7f94a671a0569b988d149fb2ff01fa6fa98235 100644 --- a/openair3/NAS/UE/nas_user.h +++ b/openair3/NAS/UE/nas_user.h @@ -40,6 +40,9 @@ Description NAS procedure functions triggered by the user #include "commonDef.h" #include "networkDef.h" +#include "emm_main.h" +#include "esm_ebr.h" +#include "user_defs.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -57,13 +60,13 @@ Description NAS procedure functions triggered by the user /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -void nas_user_initialize(emm_indication_callback_t emm_cb, +void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, esm_indication_callback_t esm_cb, const char *version); -int nas_user_receive_and_process(int * fd, char *message); +int nas_user_receive_and_process(nas_user_t *user, char *message); -int nas_user_process_data(const void *data); +int nas_user_process_data(nas_user_t *user, const void *data); -const void *nas_user_get_data(void); +const void *nas_user_get_data(nas_user_t *nas_user); #endif /* __NAS_USER_H__*/ diff --git a/openair3/NAS/UE/user_defs.h b/openair3/NAS/UE/user_defs.h new file mode 100644 index 0000000000000000000000000000000000000000..c27cf1320ee1708e0f9d9e03760f6030e2e18728 --- /dev/null +++ b/openair3/NAS/UE/user_defs.h @@ -0,0 +1,84 @@ +/* + * 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.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.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 + */ + +/***************************************************************************** +Source user_defs.h + +Version 0.1 + +Date 2016/07/01 + +Product NAS stack + +Subsystem NAS main process + +Author Frederic Leroy + +Description NAS type definition to manage a user equipment + +*****************************************************************************/ +#ifndef __USER_DEFS_H__ +#define __USER_DEFS_H__ + +#include "nas_proc_defs.h" +#include "esmData.h" +#include "esm_pt_defs.h" +#include "EMM/emm_fsm_defs.h" +#include "EMM/emmData.h" +#include "EMM/Authentication.h" +#include "EMM/IdleMode_defs.h" +#include "EMM/LowerLayer_defs.h" +#include "API/USIM/usim_api.h" +#include "API/USER/user_api_defs.h" +#include "SecurityModeControl.h" +#include "userDef.h" +#include "at_response.h" + +typedef struct { + int ueid; /* UE lower layer identifier */ + proc_data_t proc; + // Eps Session Management + esm_data_t *esm_data; // ESM internal data (used within ESM only) + esm_pt_data_t *esm_pt_data; + esm_ebr_data_t *esm_ebr_data; // EPS bearer contexts + default_eps_bearer_context_data_t *default_eps_bearer_context_data; + // Eps Mobility Management + emm_fsm_state_t emm_fsm_status; // Current EPS Mobility Management status + emm_data_t *emm_data; // EPS mobility management data + const char *emm_nvdata_store; + emm_plmn_list_t *emm_plmn_list; // list of PLMN identities + authentication_data_t *authentication_data; + security_data_t *security_data; //Internal data used for security mode control procedure + // Hardware persistent storage + usim_data_t usim_data; // USIM application data + const char *usim_data_store; // USIM application data filename + user_nvdata_t *nas_user_nvdata; //UE parameters stored in the UE's non-volatile memory device + const char *user_nvdata_store; //UE parameters stored in the UE's non-volatile memory device + // + nas_user_context_t *nas_user_context; + at_response_t *at_response; // data structure returned to the user as the result of NAS procedure function call + // + user_at_commands_t *user_at_commands; //decoded data received from the user application layer + user_api_id_t *user_api_id; + lowerlayer_data_t *lowerlayer_data; +} nas_user_t; + +#endif diff --git a/pre-commit b/pre-commit new file mode 100644 index 0000000000000000000000000000000000000000..82587fce34c8bd8df74b1a87e0ce6bb19ce18679 --- /dev/null +++ b/pre-commit @@ -0,0 +1,31 @@ + +#!/bin/bash +# Installation: +# cp pre-commit .git/hooks +# chmod +x .git/hooks/pre-commit + +OPTIONS="--convert-tabs --indent=spaces=2 --indent-switches --indent-col1-comments --break-blocks --delete-empty-lines --align-pointer=name --keep-one-line-blocks --keep-one-line-statements --lineend=linux" + +RETURN=0 +ASTYLE=$(which astyle) +if [ $? -ne 0 ]; then + echo "[!] astyle not installed. Unable to check source file format policy." >&2 + exit 1 +fi + +FILES=`git diff --cached --name-only --diff-filter=ACMR | grep -E "\.(c|cpp|h)$"` +for FILE in $FILES; do + $ASTYLE $OPTIONS < $FILE | cmp -s $FILE - + if [ $? -ne 0 ]; then + echo "[!] $FILE does not respect the agreed coding style." >&2 + RETURN=1 + fi +done + +if [ $RETURN -eq 1 ]; then + echo "" >&2 + echo "Make sure you have run astyle with the following options:" >&2 + echo $OPTIONS >&2 +fi + +exit $RETURN \ No newline at end of file diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 7433b5d6187ae0418f35dd1ccda7458c5089b5e9..19036de20461bebb4a90a103e43d88898d378975 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -139,11 +139,6 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) { int rc=0; - //ToDo: EXMIMO harmonization is not complete. That is the reason for this ifdef - #ifdef EXMIMO - int device_init(openair0_device *device, openair0_config_t *openair0_cfg); - rc = device_init(device, openair0_cfg); - #else rc=load_lib(device, openair0_cfg, NULL,BBU_LOCAL_RADIO_HEAD ); if ( rc >= 0) { if ( set_device(device) < 0) { @@ -151,7 +146,6 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf return -1; } } - #endif return rc; } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 2eb0a506be8f840c34ac5de1cb7f7a5ca9763fc3..be69a7027a77e863bfa75f2cb5ed3b576ca30b2d 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -242,6 +242,8 @@ typedef struct { uint8_t iq_txshift; //! transport type preference (RAW/UDP) uint8_t transp_preference; + //! compression enable (0: No comp/ 1: A-LAW) + uint8_t if_compress; //! radio front end preference (EXMIMO,USRP, BALDERF,LMSSDR) uint8_t rf_preference; } eth_params_t; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 5815f2b1a66797cadd6544bbfab7f6a0dce398c7..4cf04064b156f439698c964da8bd13041eba9aab 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -145,21 +145,28 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi memcpy(buff2,(void*)ð->eh,MAC_HEADER_SIZE_BYTES); *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t))=1+(i<<1); *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = timestamp; + + int sent_byte; + if (eth->compression == ALAW_COMPRESS) { + sent_byte = RAW_PACKET_SIZE_BYTES_ALAW(nsamps); + } else { + sent_byte = RAW_PACKET_SIZE_BYTES(nsamps); + } /*printf("[RRH]write mod_%d %d , len %d, buff %p \n", Mod_id,eth->sockfd[Mod_id],RAW_PACKET_SIZE_BYTES(nsamps), buff2);*/ - while(bytes_sent < RAW_PACKET_SIZE_BYTES(nsamps)) { + while(bytes_sent < sent_byte) { #if DEBUG printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n", (void *)(buff2+bytes_sent), - RAW_PACKET_SIZE_BYTES(nsamps) - bytes_sent, + sent_byte - bytes_sent, bytes_sent); #endif /* Send packet */ bytes_sent += send(eth->sockfd, buff2, - RAW_PACKET_SIZE_BYTES(nsamps), + sent_byte, sendto_flag); if ( bytes_sent == -1) { eth->num_tx_errors++; @@ -172,7 +179,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), bytes_sent); - dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps), TX_FLAG); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, sent_byte, TX_FLAG); #endif eth->tx_actual_nsamps=bytes_sent>>2; eth->tx_count++; @@ -240,6 +247,8 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi int i=0; eth_state_t *eth = (eth_state_t*)device->priv; int rcvfrom_flag =0; + int block_cnt=0; + int again_cnt=0; eth->rx_nsamps=nsamps; @@ -247,25 +256,54 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi /* buff[i] points to the position in rx buffer where the payload to be received will be placed buff2 points to the position in rx buffer where the packet header will be placed */ void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES); - + /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/ struct ether_header temp = *(struct ether_header *)buff2; int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES); openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); - + bytes_received=0; + int receive_bytes; + if (eth->compression == ALAW_COMPRESS) { + receive_bytes = RAW_PACKET_SIZE_BYTES_ALAW(nsamps); + } else { + receive_bytes = RAW_PACKET_SIZE_BYTES(nsamps); + } - while(bytes_received < RAW_PACKET_SIZE_BYTES(nsamps)) { + while(bytes_received < receive_bytes) { + again: bytes_received +=recv(eth->sockfd, buff2, - RAW_PACKET_SIZE_BYTES(nsamps), + receive_bytes, rcvfrom_flag); - + if (bytes_received ==-1) { eth->num_rx_errors++; - perror("ETHERNET IF5 READ: "); - if (errno == EAGAIN) continue; - exit(-1); + if (errno == EAGAIN) { + again_cnt++; + usleep(10); + if (again_cnt == 1000) { + perror("ETHERNET IF5 READ (EAGAIN): "); + exit(-1); + } else { + printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n"); + goto again; + } + } else if (errno == EWOULDBLOCK) { + block_cnt++; + usleep(10); + if (block_cnt == 1000) { + perror("ETHERNET IF5 READ (EWOULDBLOCK): "); + exit(-1); + } else { + printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); + goto again; + } + } else { + perror("ETHERNET IF5 READ"); + printf("(%s):\n", strerror(errno)); + exit(-1); + } } else { /* store the timestamp value from packet's header */ *timestamp = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); @@ -280,7 +318,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), bytes_received); - dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps),RX_FLAG); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, receive_bytes, RX_FLAG); #endif @@ -303,19 +341,43 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t; IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES); + int block_cnt=0; + int again_cnt=0; -#ifdef DEBUG - printf("Reading from device %p, eth %p, sockfd %d\n",device,eth,eth->sockfd); -#endif - - bytes_received = recv(eth->sockfd, - buff[0], - packet_size, - MSG_PEEK); - if (bytes_received ==-1) { - eth->num_rx_errors++; - perror("ETHERNET IF4p5 READ (header): "); - exit(-1); + while (bytes_received < packet_size) { + again: + bytes_received = recv(eth->sockfd, + buff[0], + packet_size, + MSG_PEEK); + if (bytes_received ==-1) { + eth->num_rx_errors++; + if (errno == EAGAIN) { + again_cnt++; + usleep(10); + if (again_cnt == 1000) { + perror("ETHERNET IF4p5 READ (EAGAIN): "); + exit(-1); + } else { + printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n"); + goto again; + } + } else if (errno == EWOULDBLOCK) { + block_cnt++; + usleep(10); + if (block_cnt == 1000) { + perror("ETHERNET IF4p5 READ (EWOULDBLOCK): "); + exit(-1); + } else { + printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); + goto again; + } + } else { + perror("ETHERNET IF4p5 READ"); + printf("(%s):\n", strerror(errno)); + exit(-1); + } + } } #ifdef DEBUG for (int i=0;i<packet_size;i++) @@ -331,8 +393,7 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks); } else { packet_size = RAW_IF4p5_PRACH_SIZE_BYTES; - } - + } while(bytes_received < packet_size) { bytes_received = recv(eth->sockfd, @@ -357,7 +418,6 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { // Read nblocks info from packet itself - int nblocks = nsamps; int bytes_received=0; eth_state_t *eth = (eth_state_t*)device->priv; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index c151ab11ff9464918b33f75871edfba8d0862fea..9f6c01afed27244a639bde533291a4dafa635b2b 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -139,7 +139,7 @@ int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestam IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0]); int block_cnt=0; - int again_cnt=0; + //int again_cnt=0; packet_size = max(UDP_IF4p5_PRACH_SIZE_BYTES, max(UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks), UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks))); while(bytes_received == -1) { @@ -262,23 +262,30 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi // eth->pck_header.seq_num = pck_seq_num; //eth->pck_header.antenna_id = 1+(i<<1); //eth->pck_header.timestamp = timestamp; - *(uint16_t *)buff2 = pck_seq_num; + *(uint16_t *)buff2 = eth->pck_seq_num; *(uint16_t *)(buff2 + sizeof(uint16_t)) = 1+(i<<1); *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, pck_seq_num); - + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, eth->pck_seq_num); - while(bytes_sent < UDP_PACKET_SIZE_BYTES(nsamps)) { + int sent_byte; + if (eth->compression == ALAW_COMPRESS) { + sent_byte = UDP_PACKET_SIZE_BYTES_ALAW(nsamps); + } else { + sent_byte = UDP_PACKET_SIZE_BYTES(nsamps); + } + + //while(bytes_sent < sent_byte) { + //printf("eth->pck_seq_num: %d\n", eth->pck_seq_num); #if DEBUG printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n", (void *)(buff2+bytes_sent), - UDP_PACKET_SIZE_BYTES(nsamps) - bytes_sent, + sent_byte - bytes_sent, bytes_sent); #endif /* Send packet */ bytes_sent += sendto(eth->sockfd, buff2, - UDP_PACKET_SIZE_BYTES(nsamps), + sent_byte, sendto_flag, (struct sockaddr*)ð->dest_addr, eth->addr_len); @@ -294,14 +301,15 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi *(int16_t *)(buff2 + sizeof(int16_t)), *(openair0_timestamp *)(buff2 + sizeof(int32_t)), bytes_sent); - dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps), TX_FLAG); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, sent_byte, TX_FLAG); #endif eth->tx_actual_nsamps=bytes_sent>>2; eth->tx_count++; - pck_seq_num++; - if ( pck_seq_num > MAX_PACKET_SEQ_NUM(nsamps,device->openair0_cfg->samples_per_frame) ) pck_seq_num = 1; + eth->pck_seq_num++; + if ( eth->pck_seq_num > MAX_PACKET_SEQ_NUM(nsamps,device->openair0_cfg->samples_per_frame) ) eth->pck_seq_num = 1; } - } + //} + /* tx buffer values restored */ *(int32_t *)buff2 = temp0; *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; @@ -335,19 +343,24 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi bytes_received=0; block_cnt=0; + int receive_bytes; + if (eth->compression == ALAW_COMPRESS) { + receive_bytes = UDP_PACKET_SIZE_BYTES_ALAW(nsamps); + } else { + receive_bytes = UDP_PACKET_SIZE_BYTES(nsamps); + } - - while(bytes_received < UDP_PACKET_SIZE_BYTES(nsamps)) { + while(bytes_received < receive_bytes) { again: #if DEBUG printf("------- RX------: buff2 current position=%d remaining_bytes=%d bytes_recv=%d \n", (void *)(buff2+bytes_received), - UDP_PACKET_SIZE_BYTES(nsamps) - bytes_received, + receive_bytes - bytes_received, bytes_received); #endif bytes_received +=recvfrom(eth->sockfd, buff2, - UDP_PACKET_SIZE_BYTES(nsamps), + receive_bytes, rcvfrom_flag, (struct sockaddr *)ð->dest_addr, (socklen_t *)ð->addr_len); @@ -382,28 +395,29 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi *(int16_t *)(buff2 + sizeof(int16_t)), *(openair0_timestamp *)(buff2 + sizeof(int32_t)), bytes_received); - dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, receive_bytes, RX_FLAG); #endif /* store the timestamp value from packet's header */ *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); /* store the sequence number of the previous packet received */ - if (pck_seq_num_cur == 0) { - pck_seq_num_prev = *(uint16_t *)buff2; + if (eth->pck_seq_num_cur == 0) { + eth->pck_seq_num_prev = *(uint16_t *)buff2; } else { - pck_seq_num_prev = pck_seq_num_cur; + eth->pck_seq_num_prev = eth->pck_seq_num_cur; } /* get the packet sequence number from packet's header */ - pck_seq_num_cur = *(uint16_t *)buff2; - //printf("cur=%d prev=%d buff=%d\n",pck_seq_num_cur,pck_seq_num_prev,*(uint16_t *)(buff2)); - if ( ( pck_seq_num_cur != (pck_seq_num_prev + 1) ) && !((pck_seq_num_prev==MAX_PACKET_SEQ_NUM(nsamps,device->openair0_cfg->samples_per_frame)) && (pck_seq_num_cur==1 )) && !((pck_seq_num_prev==1) && (pck_seq_num_cur==1))) { - printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev,(int)*timestamp); + eth->pck_seq_num_cur = *(uint16_t *)buff2; + if ( ( eth->pck_seq_num_cur != (eth->pck_seq_num_prev + 1) ) && !((eth->pck_seq_num_prev==MAX_PACKET_SEQ_NUM(nsamps,device->openair0_cfg->samples_per_frame)) && (eth->pck_seq_num_cur==1 )) && !((eth->pck_seq_num_prev==1) && (eth->pck_seq_num_cur==1))) { + //#if DEBUG + printf("Out of order packet received: current_packet=%d previous_packet=%d timestamp=%"PRId64"\n",eth->pck_seq_num_cur,eth->pck_seq_num_prev,*timestamp); + //#endif } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,pck_seq_num_cur); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,pck_seq_num_prev); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,eth->pck_seq_num_cur); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,eth->pck_seq_num_prev); eth->rx_actual_nsamps=bytes_received>>2; eth->rx_count++; - } + } } /* tx buffer values restored */ @@ -434,7 +448,7 @@ int eth_set_dev_conf_udp(openair0_device *device) { if (sendto(eth->sockfd,msg,msg_len,0,(struct sockaddr *)ð->dest_addr,eth->addr_len)==-1) { perror("ETHERNET: sendto conf_udp"); - printf("addr_len : %d, msg_len %d\n",eth->addr_len,msg_len); + printf("addr_len : %d, msg_len %zd\n",eth->addr_len,msg_len); exit(0); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index d30f8faed827d75febd8610300f9d674a35f902b..f22206eec8018a16da10289772488d0edcdd56f5 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -41,16 +41,24 @@ #include <netinet/ether.h> #include <unistd.h> #include <errno.h> +#include <linux/sysctl.h> +#include <sys/sysctl.h> #include "common_lib.h" #include "ethernet_lib.h" + +int num_devices_eth = 0; +struct sockaddr_in dest_addr[MAX_INST]; +int dest_addr_len[MAX_INST]; + + int trx_eth_start(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; /* initialize socket */ - if (eth->flags == ETH_RAW_MODE) { + if (eth->flags == ETH_RAW_MODE) { printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n"); if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ @@ -60,10 +68,14 @@ int trx_eth_start(openair0_device *device) { if(eth_get_dev_conf_raw(device)!=0) return -1; } /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + if(eth->compression == ALAW_COMPRESS) { + if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES_ALAW(device->openair0_cfg->samples_per_packet))!=0) return -1; + } else { + if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + } if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_RAW_IF4p5_MODE) { - + printf("Setting ETHERNET to ETH_RAW_IF4p5_MODE\n"); if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ @@ -74,11 +86,11 @@ int trx_eth_start(openair0_device *device) { } /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; - + if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_UDP_IF4p5_MODE) { printf("Setting ETHERNET to UDP_IF4p5_MODE\n"); - if (eth_socket_init_udp(device)!=0) return -1; + if (eth_socket_init_udp(device)!=0) return -1; if (device->host_type == BBU_HOST) { if(eth_set_dev_conf_udp(device)!=0) return -1; } else { @@ -113,7 +125,9 @@ int trx_eth_start(openair0_device *device) { /* apply additional configuration */ if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1; if(ethernet_tune (device, RCV_BUF_SIZE,2000000000)!=0) return -1; - + if(ethernet_tune (device, KERNEL_SND_BUF_MAX_SIZE, 200000000)!=0) return -1; + if(ethernet_tune (device, KERNEL_RCV_BUF_MAX_SIZE, 200000000)!=0) return -1; + return 0; } @@ -194,10 +208,12 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { eth_state_t *eth = (eth_state_t*)device->priv; struct timeval timeout; struct ifreq ifr; - char system_cmd[256]; - // char* if_name=DEFAULT_IF; - // struct in_addr ia; - // struct if_nameindex *ids; + char system_cmd[256]; + int rname[] = { CTL_NET, NET_CORE, NET_CORE_RMEM_MAX }; + int wname[] = { CTL_NET, NET_CORE, NET_CORE_WMEM_MAX }; + int namelen=3; + int newval[1]; + int newlen=sizeof(newval); int ret=0; // int i=0; @@ -281,7 +297,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { if (ret == -1) { fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); } else { - printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); } printf("[ETHERNET] Coalesce parameters %s\n",system_cmd); } else { @@ -298,7 +314,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { if (ret == -1) { fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); } else { - printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); } printf("[ETHERNET] Pause parameters %s\n",system_cmd); } else { @@ -313,14 +329,32 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { if (ret == -1) { fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); } else { - printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); } printf("[ETHERNET] Ring parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set ring parameters\n"); } break; - + case KERNEL_RCV_BUF_MAX_SIZE: + newval[0] = value; + ret=sysctl(rname, namelen, NULL, 0, newval, newlen); + if (ret) { + fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); + } else{ + printf("[ETHERNET] Kernel network receive buffer max size is set to %u\n",newval[0]); + } + break; + case KERNEL_SND_BUF_MAX_SIZE: + newval[0] = value; + ret=sysctl(wname, namelen, NULL, 0, newval, newlen); + if (ret) { + fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); + } else{ + printf("[ETHERNET] Kernel network send buffer max size is set to %u\n",newval[0]); + } + break; + default: break; } @@ -348,6 +382,15 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference); eth->flags = ETH_RAW_MODE; } + + if (eth_params->if_compress == 0) { + eth->compression = NO_COMPRESS; + } else if (eth_params->if_compress == 1) { + eth->compression = ALAW_COMPRESS; + } else { + printf("transport_init: Unknown compression scheme %d - default to ALAW", eth_params->if_compress); + eth->compression = ALAW_COMPRESS; + } printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); device->Mod_id = 0;//num_devices_eth++; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 9f555beaa9dea29bc862ed5a54953051eff09496..50a573800752a0ba09fa17d7cb5e7e4a0a85375e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -78,6 +78,8 @@ typedef struct { unsigned int tx_timeout_ms; /*!\brief runtime flags */ uint32_t flags; + /*!\compression enalbe */ + uint32_t compression; /*!\ time offset between transmiter timestamp and receiver timestamp */ double tdiff; /*!\ calibration */ @@ -98,7 +100,7 @@ typedef struct { int num_seq_errors; /*!\brief number of errors in interface's receiver */ int num_rx_errors; - /*!\brief umber of errors in interface's transmitter */ + /*!\brief number of errors in interface's transmitter */ int num_tx_errors; /*!\brief current TX timestamp */ @@ -117,6 +119,12 @@ typedef struct { uint64_t tx_count; /*!\brief number of packets received */ uint64_t rx_count; + /*!\brief TX sequence number*/ + uint16_t pck_seq_num; + /*!\brief Current RX sequence number*/ + uint16_t pck_seq_num_cur; + /*!\brief Previous RX sequence number */ + uint16_t pck_seq_num_prev; struct ether_header eh; @@ -155,6 +163,10 @@ typedef enum { COALESCE_PAR, /*!\brief pause parameters of ethernet device */ PAUSE_PAR, + /*!\brief kernel network receive buffer maximun size */ + KERNEL_RCV_BUF_MAX_SIZE, + /*!\brief kernel network send buffer maximun size */ + KERNEL_SND_BUF_MAX_SIZE, MAX_OPT } eth_opt_t; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index f4d6d6df1c616aa61c004df8fa4239504609d199..6c51db64cecd48e6c80495f39eed5a1698ecbc06 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -49,6 +49,9 @@ // COMMOM HEADER LENGTHS +#define NO_COMPRESS 0 +#define ALAW_COMPRESS 1 + #define UDP_HEADER_SIZE_BYTES 8 #define IPV4_HEADER_SIZE_BYTES 60 // This is the maximum IPv4 header length @@ -59,9 +62,13 @@ #define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +#define PAYLOAD_SIZE_BYTES_ALAW(nsamps) (nsamps<<1) +#define UDP_PACKET_SIZE_BYTES_ALAW(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES_ALAW(nsamps)) +#define RAW_PACKET_SIZE_BYTES_ALAW(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES_ALAW(nsamps)) + // Packet sizes for IF4p5 interface format #define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(uint16_t)*scaled_nblocks) -#define PRACH_HARD_CODED_NUM_SAMPLES (839*4) +#define PRACH_HARD_CODED_NUM_SAMPLES (839*2) #define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*PRACH_HARD_CODED_NUM_SAMPLES) // FIX hard coded prach size #define RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) diff --git a/targets/ARCH/EXMIMO/DRIVER/eurecom/exmimo_fw.c b/targets/ARCH/EXMIMO/DRIVER/eurecom/exmimo_fw.c index 993b2db2eeb1ec21d1238f4a5cdb764d3974b79f..766bb6eb74993c023111574f70f9099421a2dbe1 100644 --- a/targets/ARCH/EXMIMO/DRIVER/eurecom/exmimo_fw.c +++ b/targets/ARCH/EXMIMO/DRIVER/eurecom/exmimo_fw.c @@ -193,7 +193,7 @@ int exmimo_assign_shm_vars(int card_id) int exmimo_allocate_rx_tx_buffers(int card_id) { size_t size; - int j,i; + int j; dma_addr_t dma_addr_dummy; // Round up to the next PAGE_SIZE (typ. 4096 bytes) size = (ADAC_BUFFERSZ_PERCHAN_B >> PAGE_SHIFT) + 1; @@ -243,8 +243,6 @@ int exmimo_allocate_rx_tx_buffers(int card_id) */ int exmimo_memory_alloc(int card) { - int i; - if ( bigshm_init( card ) ) { printk("exmimo_memory_alloc(): bigshm_init failed for card %d.\n", card); return -ENOMEM; diff --git a/targets/ARCH/LMSSDR/LimeSDR_above_1p8GHz.ini b/targets/ARCH/LMSSDR/LimeSDR_above_1p8GHz.ini new file mode 100755 index 0000000000000000000000000000000000000000..56ff3527373c61963d70b5e0a878b7ef0febeaa4 --- /dev/null +++ b/targets/ARCH/LMSSDR/LimeSDR_above_1p8GHz.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0020=0xFFFD +0x0021=0x0E9F +0x0022=0x07FF +0x0023=0x5550 +0x0024=0xB1E4 +0x0025=0x0101 +0x0026=0x0101 +0x0027=0xB1E4 +0x0028=0x0101 +0x0029=0x0101 +0x002A=0x0086 +0x002B=0x0038 +0x002C=0x0000 +0x002D=0x0000 +0x002E=0x0000 +0x002F=0x3840 +0x0081=0x0000 +0x0082=0x8003 +0x0084=0x0400 +0x0085=0x0001 +0x0086=0x4101 +0x0087=0x0000 +0x0088=0x04B0 +0x0089=0x1090 +0x008A=0x0514 +0x008B=0x2102 +0x008C=0x267B +0x0092=0x0001 +0x0093=0x0000 +0x0094=0x0000 +0x0095=0x0000 +0x0096=0x0000 +0x0097=0x0000 +0x0098=0x0000 +0x0099=0x6565 +0x009A=0x658C +0x009B=0x6565 +0x009C=0x658C +0x009D=0x6565 +0x009E=0x658C +0x009F=0x658C +0x00A0=0x6565 +0x00A1=0x6565 +0x00A2=0x6565 +0x00A3=0x6565 +0x00A4=0x6565 +0x00A5=0x6565 +0x00A6=0x000F +0x00A7=0x6565 +0x00A8=0x0000 +0x00A9=0x0000 +0x00AA=0x0000 +0x00AB=0x0040 +0x00AC=0x0000 +0x00AD=0x03FF +0x00AE=0x0000 +0x0100=0x3409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0612 +0x0104=0x0088 +0x0105=0x0011 +0x0106=0x318C +0x0107=0x318C +0x0108=0x2826 +0x0109=0x6104 +0x010A=0x17BD +0x010C=0x8865 +0x010D=0x015A +0x010E=0x0000 +0x010F=0x3042 +0x0110=0x0BFF +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x0303 +0x0114=0x00D0 +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x528C +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0x2000 +0x011E=0x06E4 +0x011F=0x3640 +0x0120=0xB9FF +0x0121=0x341C +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0081 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0170 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x8000 +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x8081 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0003 +0x040B=0x000F +0x040C=0x00F8 +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x2B55 +0x0443=0x5540 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[lms7002_registers_b] +0x0100=0x340F +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0612 +0x0104=0x0088 +0x0105=0x001F +0x0106=0x3182 +0x0107=0x318C +0x0108=0x9442 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x88FF +0x010D=0x001E +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x03C3 +0x0114=0x00D0 +0x0115=0x000F +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x5280 +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0x1555 +0x011E=0x0747 +0x011F=0x3640 +0x0120=0xB9FF +0x0121=0x360C +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0101 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x01F0 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0105 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0000 +0x040B=0x7FFF +0x040C=0x00FF +0x040D=0x0000 +0x040E=0x0002 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0000 +0x0443=0x0000 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[reference_clocks] +sxt_ref_clk_mhz=30.72 +sxr_ref_clk_mhz=30.72 diff --git a/targets/ARCH/LMSSDR/LimeSDR_above_1p8GHz_1v4.ini b/targets/ARCH/LMSSDR/LimeSDR_above_1p8GHz_1v4.ini new file mode 100755 index 0000000000000000000000000000000000000000..9503891fb9220223c5f2808d00686112e73c3735 --- /dev/null +++ b/targets/ARCH/LMSSDR/LimeSDR_above_1p8GHz_1v4.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0020=0xFFFD +0x0021=0x0E9F +0x0022=0x07FF +0x0023=0x5550 +0x0024=0xB1E4 +0x0025=0x0101 +0x0026=0x0101 +0x0027=0xB1E4 +0x0028=0x0101 +0x0029=0x0101 +0x002A=0x0086 +0x002B=0x0038 +0x002C=0x0000 +0x002D=0x0000 +0x002E=0x0000 +0x002F=0x3840 +0x0081=0x0000 +0x0082=0x800B +0x0084=0x0400 +0x0085=0x0001 +0x0086=0x4101 +0x0087=0x0000 +0x0088=0x04B0 +0x0089=0x1090 +0x008A=0x0514 +0x008B=0x2136 +0x008C=0x267B +0x0092=0x0001 +0x0093=0x0000 +0x0094=0x0000 +0x0095=0x0000 +0x0096=0x0000 +0x0097=0x0000 +0x0098=0x0000 +0x0099=0x6565 +0x009A=0x658C +0x009B=0x6565 +0x009C=0x658C +0x009D=0x6565 +0x009E=0x658C +0x009F=0x658C +0x00A0=0x6565 +0x00A1=0x6565 +0x00A2=0x6565 +0x00A3=0x6565 +0x00A4=0x6565 +0x00A5=0x6565 +0x00A6=0x000F +0x00A7=0x6565 +0x00A8=0x0000 +0x00A9=0x0000 +0x00AA=0x0000 +0x00AB=0x0040 +0x00AC=0x0000 +0x00AD=0x03FF +0x00AE=0x0000 +0x0100=0x3409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0612 +0x0104=0x0088 +0x0105=0x0011 +0x0106=0x318C +0x0107=0x318C +0x0108=0x218C +0x0109=0x6104 +0x010A=0x17BD +0x010C=0x8865 +0x010D=0x00DE +0x010E=0x0000 +0x010F=0x30C6 +0x0110=0x0BFF +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x0303 +0x0114=0x00D0 +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x528C +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0x2000 +0x011E=0x06E4 +0x011F=0x3640 +0x0120=0xB9FF +0x0121=0x341C +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0081 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0170 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x8000 +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x8081 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0003 +0x040B=0x000F +0x040C=0x00F8 +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x2B55 +0x0443=0x5540 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[lms7002_registers_b] +0x0100=0x340F +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0612 +0x0104=0x0088 +0x0105=0x001F +0x0106=0x3182 +0x0107=0x318C +0x0108=0x9442 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x88FF +0x010D=0x001E +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x03C3 +0x0114=0x00D0 +0x0115=0x000F +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x5280 +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0x1555 +0x011E=0x0747 +0x011F=0x3640 +0x0120=0xB9FF +0x0121=0x360C +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0101 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x01F0 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0105 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0000 +0x040B=0x7FFF +0x040C=0x00FF +0x040D=0x0000 +0x040E=0x0002 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0000 +0x0443=0x0000 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[reference_clocks] +sxt_ref_clk_mhz=30.72 +sxr_ref_clk_mhz=30.72 diff --git a/targets/ARCH/LMSSDR/LimeSDR_below_1p8GHz.ini b/targets/ARCH/LMSSDR/LimeSDR_below_1p8GHz.ini new file mode 100755 index 0000000000000000000000000000000000000000..dda51f7f27d97511d742cef79f99c99f208dc310 --- /dev/null +++ b/targets/ARCH/LMSSDR/LimeSDR_below_1p8GHz.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0020=0xFFFD +0x0021=0x0E9F +0x0022=0x07FF +0x0023=0x5550 +0x0024=0xB1E4 +0x0025=0x0101 +0x0026=0x0101 +0x0027=0xB1E4 +0x0028=0x0101 +0x0029=0x0101 +0x002A=0x0086 +0x002B=0x0038 +0x002C=0x0000 +0x002D=0x0000 +0x002E=0x0000 +0x002F=0x3840 +0x0081=0x0000 +0x0082=0x8003 +0x0084=0x0400 +0x0085=0x0001 +0x0086=0x4101 +0x0087=0x0000 +0x0088=0x04B0 +0x0089=0x1090 +0x008A=0x0514 +0x008B=0x2102 +0x008C=0x267B +0x0092=0x0001 +0x0093=0x0000 +0x0094=0x0000 +0x0095=0x0000 +0x0096=0x0000 +0x0097=0x0000 +0x0098=0x0000 +0x0099=0x6565 +0x009A=0x658C +0x009B=0x6565 +0x009C=0x658C +0x009D=0x6565 +0x009E=0x658C +0x009F=0x658C +0x00A0=0x6565 +0x00A1=0x6565 +0x00A2=0x6565 +0x00A3=0x6565 +0x00A4=0x6565 +0x00A5=0x6565 +0x00A6=0x000F +0x00A7=0x6565 +0x00A8=0x0000 +0x00A9=0x0000 +0x00AA=0x0000 +0x00AB=0x0040 +0x00AC=0x0000 +0x00AD=0x03FF +0x00AE=0x0000 +0x0100=0x3409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0A12 +0x0104=0x0088 +0x0105=0x0011 +0x0106=0x318C +0x0107=0x318C +0x0108=0x2826 +0x0109=0x6104 +0x010A=0x17BD +0x010C=0x8865 +0x010D=0x01DC +0x010E=0x0000 +0x010F=0x3042 +0x0110=0x0BFF +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x0303 +0x0114=0x00D0 +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x528C +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0xC000 +0x011E=0x068F +0x011F=0x3680 +0x0120=0xB9FF +0x0121=0x3234 +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0081 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0170 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x8000 +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x8081 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0003 +0x040B=0x000F +0x040C=0x00F8 +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x2B55 +0x0443=0x5540 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[lms7002_registers_b] +0x0100=0x340F +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0612 +0x0104=0x0088 +0x0105=0x001F +0x0106=0x3182 +0x0107=0x318C +0x0108=0x9442 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x88FF +0x010D=0x001E +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x03C3 +0x0114=0x00D0 +0x0115=0x000F +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x5280 +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0xC000 +0x011E=0x06F3 +0x011F=0x3680 +0x0120=0xB9FF +0x0121=0x346C +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0101 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x01F0 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0105 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0000 +0x040B=0x7FFF +0x040C=0x00FF +0x040D=0x0000 +0x040E=0x0002 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0000 +0x0443=0x0000 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[reference_clocks] +sxt_ref_clk_mhz=30.72 +sxr_ref_clk_mhz=30.72 diff --git a/targets/ARCH/LMSSDR/LimeSDR_below_1p8GHz_1v4.ini b/targets/ARCH/LMSSDR/LimeSDR_below_1p8GHz_1v4.ini new file mode 100755 index 0000000000000000000000000000000000000000..7c94b3dd5bf801dc3370a07bb6c38a4aafd6a29e --- /dev/null +++ b/targets/ARCH/LMSSDR/LimeSDR_below_1p8GHz_1v4.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0020=0xFFFD +0x0021=0x0E9F +0x0022=0x07FF +0x0023=0x5550 +0x0024=0xB1E4 +0x0025=0x0101 +0x0026=0x0101 +0x0027=0xB1E4 +0x0028=0x0101 +0x0029=0x0101 +0x002A=0x0086 +0x002B=0x0038 +0x002C=0x0000 +0x002D=0x0000 +0x002E=0x0000 +0x002F=0x3841 +0x0081=0x0000 +0x0082=0x800B +0x0084=0x0400 +0x0085=0x0001 +0x0086=0x4101 +0x0087=0x0000 +0x0088=0x04B0 +0x0089=0x1090 +0x008A=0x0514 +0x008B=0x2138 +0x008C=0x267B +0x0092=0x0001 +0x0093=0x0000 +0x0094=0x0000 +0x0095=0x0000 +0x0096=0x0000 +0x0097=0x0000 +0x0098=0x0000 +0x0099=0x6565 +0x009A=0x658C +0x009B=0x6565 +0x009C=0x658C +0x009D=0x6565 +0x009E=0x658C +0x009F=0x658C +0x00A0=0x6565 +0x00A1=0x6565 +0x00A2=0x6565 +0x00A3=0x6565 +0x00A4=0x6565 +0x00A5=0x6565 +0x00A6=0x000F +0x00A7=0x6565 +0x00A8=0x0000 +0x00A9=0x0000 +0x00AA=0x0000 +0x00AB=0x0040 +0x00AC=0x0000 +0x00AD=0x03FF +0x00AE=0x0000 +0x0100=0x3409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0A12 +0x0104=0x0088 +0x0105=0x0011 +0x0106=0x318C +0x0107=0x318C +0x0108=0x298C +0x0109=0x6104 +0x010A=0x17BD +0x010C=0x8865 +0x010D=0x015A +0x010E=0x0000 +0x010F=0x30C6 +0x0110=0x0BFF +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x0303 +0x0114=0x00D0 +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x528C +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0xC000 +0x011E=0x068F +0x011F=0x3680 +0x0120=0xB9FF +0x0121=0x3234 +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0081 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0170 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x8000 +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x8081 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0003 +0x040B=0x000F +0x040C=0x00F8 +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x2B55 +0x0443=0x5540 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[lms7002_registers_b] +0x0100=0x340F +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0612 +0x0104=0x0088 +0x0105=0x001F +0x0106=0x3182 +0x0107=0x318C +0x0108=0x9442 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x88FF +0x010D=0x001E +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0x9407 +0x0113=0x03C3 +0x0114=0x00D0 +0x0115=0x000F +0x0116=0x8180 +0x0117=0x1217 +0x0118=0x018C +0x0119=0x5280 +0x011A=0x3E03 +0x011C=0xAD41 +0x011D=0xC000 +0x011E=0x06F3 +0x011F=0x3680 +0x0120=0xB9FF +0x0121=0x346C +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0101 +0x0201=0x07FF +0x0202=0x07FF +0x0203=0x0000 +0x0204=0x0000 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x01F0 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x0000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0105 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0000 +0x040B=0x7FFF +0x040C=0x00FF +0x040D=0x0000 +0x040E=0x0002 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0000 +0x0443=0x0000 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[reference_clocks] +sxt_ref_clk_mhz=30.72 +sxr_ref_clk_mhz=30.72 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index 3a9878e82b182c670602344442321b6ffdb52804..2dec4ff22df96683b897b76352eb924f44ec4abf 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -45,6 +45,14 @@ lms_device_t* lms_device; lms_stream_t rx_stream; lms_stream_t tx_stream; +/* We have a strange behavior when we just start reading + * from the device (inconsistent values of the timestamp). + * A quick solution is to discard the very first read packet + * after a "start". + * The following global variable "first_rx" serves that purpose. + */ +static int first_rx = 0; + #define RXDCLENGTH 4096 #define NUMBUFF 32 @@ -94,6 +102,10 @@ int trx_lms_read(openair0_device *device, openair0_timestamp *ptimestamp, void * meta.flushPartialPacket = false; int ret; + if (first_rx == 1) { + first_rx = 0; + ret = LMS_RecvStream(&rx_stream,buff[0],nsamps,&meta,50); + } ret = LMS_RecvStream(&rx_stream,buff[0],nsamps,&meta,50); *ptimestamp = meta.timestamp; return ret; @@ -128,30 +140,20 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { /*! \brief Set Gains (TX/RX) on LMSSDR * \param device the hardware to use * \param openair0_cfg openair0 Config structure - * \returns 0 in success + * \returns 0 in success, -1 on error */ int trx_lms_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { + int ret = 0; - LMS_SetNormalizedGain(lms_device, LMS_CH_TX, 0, openair0_cfg[0].tx_gain[0]/100.0); - - // RX gains, use low-level setting - - double gv = openair0_cfg[0].rx_gain[0] - openair0_cfg[0].rx_gain_offset[0]; - if (gv > 31) { - printf("RX Gain 0 too high, reduce by %f dB\n",gv-31); - gv = 31; - } - if (gv < 0) { - printf("RX Gain 0 too low, increase by %f dB\n",-gv); - gv = 0; - } - printf("[LMS] Setting 7002M G_PGA_RBB to %d\n", (int16_t)gv); - LMS7002M lms7; - lms7.SetConnection(lms7.GetConnection()); - lms7.Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB),(int16_t)gv); - + if (openair0_cfg->rx_gain[0] > 70+openair0_cfg->rx_gain_offset[0]) { + printf("[LMS] Reduce RX Gain 0 by %f dB\n",openair0_cfg->rx_gain[0]-openair0_cfg->rx_gain_offset[0]-70); + ret = -1; + } + + LMS_SetGaindB(lms_device, LMS_CH_TX, 0, openair0_cfg->tx_gain[0]); + LMS_SetGaindB(lms_device, LMS_CH_RX, 0, openair0_cfg->rx_gain[0]-openair0_cfg->rx_gain_offset[0]); - return(0); + return(ret); } /*! \brief Start LMSSDR @@ -212,10 +214,11 @@ int trx_lms_start(openair0_device *device){ } printf("Set TX frequency %f MHz\n",device->openair0_cfg[0].tx_freq[0]/1e6); + /* printf("Override antenna settings to: RX1_H, TXA_2"); LMS_SetAntenna(lms_device, LMS_CH_RX, 0, 1); LMS_SetAntenna(lms_device, LMS_CH_TX, 0, 2); - + */ for (int i = 0; i< device->openair0_cfg->rx_num_channels; i++) @@ -232,6 +235,8 @@ int trx_lms_start(openair0_device *device){ } + first_rx = 1; + rx_stream.channel = 0; rx_stream.fifoSize = 256*1024; rx_stream.throughputVsLatency = 0.1; @@ -292,12 +297,21 @@ int trx_lms_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,in // 31 = 19 dB => 105 dB total gain @ 2.6 GHz /*! \brief calibration table for LMSSDR */ +// V1.2 board +rx_gain_calib_table_t calib_table_lmssdr_1v2[] = { + {3500000000.0,44.0}, // on L PAD + {2660000000.0,55.0}, // on L PAD + {2300000000.0,54.0}, // on L PAD + {1880000000.0,54.0}, // on L PAD + {816000000.0,79.0}, // on W PAD + {-1,0}}; +// V1.4 board rx_gain_calib_table_t calib_table_lmssdr[] = { - {3500000000.0,70.0}, - {2660000000.0,80.0}, - {2300000000.0,80.0}, - {1880000000.0,74.0}, // on W PAD - {816000000.0,76.0}, // on W PAD + {3500000000.0,44.0}, // on H PAD + {2660000000.0,55.0}, // on H PAD + {2300000000.0,54.0}, // on H PAD + {1880000000.0,54.0}, // on H PAD + {816000000.0,79.0}, // on L PAD {-1,0}}; @@ -344,7 +358,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){ device->type=LMSSDR_DEV; printf("LMSSDR: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); - + openair0_cfg[0].iq_txshift = 0; switch ((int)openair0_cfg[0].sample_rate) { case 30720000: // from usrp_time_offset @@ -355,9 +369,9 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){ break; case 15360000: openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 70; - openair0_cfg[0].tx_bw = 10e6; - openair0_cfg[0].rx_bw = 10e6; + openair0_cfg[0].tx_sample_advance = 50; /* TODO: to be refined */ + openair0_cfg[0].tx_bw = 15.36e6; + openair0_cfg[0].rx_bw = 15.36e6; break; case 7680000: openair0_cfg[0].samples_per_packet = 1024; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 2a2e09f40cbe800e7cd7fb654d059f88b1ff3113..df91796049332360b9265b4f7b982108d1319568 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -40,10 +40,12 @@ #include <time.h> #include "UTIL/LOG/log_extern.h" #include "common_lib.h" +#include "assertions.h" + #ifdef __SSE4_1__ # include <smmintrin.h> #endif - + #ifdef __AVX2__ # include <immintrin.h> #endif @@ -56,180 +58,133 @@ * @{ */ -/*! \brief USRP Configuration */ -typedef struct -{ - - // -------------------------------- - // variables for USRP configuration - // -------------------------------- - //! USRP device pointer - uhd::usrp::multi_usrp::sptr usrp; - //uhd::usrp::multi_usrp::sptr rx_usrp; - - //create a send streamer and a receive streamer - //! USRP TX Stream - uhd::tx_streamer::sptr tx_stream; - //! USRP RX Stream - uhd::rx_streamer::sptr rx_stream; - - //! USRP TX Metadata - uhd::tx_metadata_t tx_md; - //! USRP RX Metadata - uhd::rx_metadata_t rx_md; - - //! USRP Timestamp Information - uhd::time_spec_t tm_spec; - - //setup variables and allocate buffer - //! USRP Metadata - uhd::async_metadata_t async_md; - - //! Sampling rate - double sample_rate; - - //! time offset between transmiter timestamp and receiver timestamp; - double tdiff; - - //! TX forward samples. We use usrp_time_offset to get this value - int tx_forward_nsamps; //166 for 20Mhz - - - // -------------------------------- - // Debug and output control - // -------------------------------- - //! Number of underflows - int num_underflows; - //! Number of overflows - int num_overflows; - - //! Number of sequential errors - int num_seq_errors; - //! tx count - int64_t tx_count; - //! rx count - int64_t rx_count; - //! timestamp of RX packet - openair0_timestamp rx_timestamp; +/*! \brief USRP Configuration */ +typedef struct { + + // -------------------------------- + // variables for USRP configuration + // -------------------------------- + //! USRP device pointer + uhd::usrp::multi_usrp::sptr usrp; + + //create a send streamer and a receive streamer + //! USRP TX Stream + uhd::tx_streamer::sptr tx_stream; + //! USRP RX Stream + uhd::rx_streamer::sptr rx_stream; + + //! USRP TX Metadata + uhd::tx_metadata_t tx_md; + //! USRP RX Metadata + uhd::rx_metadata_t rx_md; + + //! Sampling rate + double sample_rate; + + //! TX forward samples. We use usrp_time_offset to get this value + int tx_forward_nsamps; //166 for 20Mhz + + // -------------------------------- + // Debug and output control + // -------------------------------- + int num_underflows; + int num_overflows; + int num_seq_errors; + int64_t tx_count; + int64_t rx_count; + //! timestamp of RX packet + openair0_timestamp rx_timestamp; } usrp_state_t; + + /*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error @param device pointer to the device structure specific to the RF hardware target */ -static int trx_usrp_start(openair0_device *device) -{ - usrp_state_t *s = (usrp_state_t*)device->priv; - - // init recv and send streaming - uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.05); - cmd.stream_now = false; // start at constant delay - s->rx_stream->issue_stream_cmd(cmd); +static int trx_usrp_start(openair0_device *device) { - s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate); - s->tx_md.has_time_spec = true; - s->tx_md.start_of_burst = true; - s->tx_md.end_of_burst = false; + usrp_state_t *s = (usrp_state_t*)device->priv; + // init recv and send streaming + uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.05); + cmd.stream_now = false; // start at constant delay + s->rx_stream->issue_stream_cmd(cmd); - s->rx_count = 0; - s->tx_count = 0; - s->rx_timestamp = 0; + s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate); + s->tx_md.has_time_spec = true; + s->tx_md.start_of_burst = true; + s->tx_md.end_of_burst = false; - return 0; + s->rx_count = 0; + s->tx_count = 0; + s->rx_timestamp = 0; + return 0; } -/*! \brief Terminate operation of the USRP transceiver -- free all associated resources +/*! \brief Terminate operation of the USRP transceiver -- free all associated resources * \param device the hardware to use */ -static void trx_usrp_end(openair0_device *device) -{ - usrp_state_t *s = (usrp_state_t*)device->priv; +static void trx_usrp_end(openair0_device *device) { + usrp_state_t *s = (usrp_state_t*)device->priv; - s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + //send a mini EOB packet + s->tx_md.end_of_burst = true; + s->tx_stream->send("", 0, s->tx_md); + s->tx_md.end_of_burst = false; - //send a mini EOB packet - s->tx_md.end_of_burst = true; - s->tx_stream->send("", 0, s->tx_md); - s->tx_md.end_of_burst = false; - } /*! \brief Called to send samples to the USRP RF target @param device pointer to the device structure specific to the RF hardware target - @param timestamp The timestamp at whicch the first sample MUST be sent + @param timestamp The timestamp at whicch the first sample MUST be sent @param buff Buffer which holds the samples @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple anteannas @param flags flags must be set to TRUE if timestamp parameter needs to be applied -*/ -static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) -{ - static long long int loop=0; - static long time_min=0, time_max=0, time_avg=0; - struct timespec tp_start, tp_end; - long time_diff; - clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start); - - int ret=0, ret_i=0; - usrp_state_t *s = (usrp_state_t*)device->priv; - - s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); - - - if(flags>0) - s->tx_md.has_time_spec = true; - else - s->tx_md.has_time_spec = false; +*/ +static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + int ret=0; + usrp_state_t *s = (usrp_state_t*)device->priv; - if (flags == 2) { // start of burst - s->tx_md.start_of_burst = true; - s->tx_md.end_of_burst = false; - } - else if (flags == 3) { // end of burst - s->tx_md.start_of_burst = false; - s->tx_md.end_of_burst = true; - } - else if (flags == 4) { // start and end - s->tx_md.start_of_burst = true; - s->tx_md.end_of_burst = true; - } - else if (flags==1) { // middle of burst - s->tx_md.start_of_burst = false; - s->tx_md.end_of_burst = false; - } - - if (cc>1) { - std::vector<void *> buff_ptrs; - for (int i=0;i<cc;i++) buff_ptrs.push_back(buff[i]); - ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3); - } - else - ret = (int)s->tx_stream->send(buff[0], nsamps, s->tx_md,1e-3); - - - - if (ret != nsamps) { - printf("[xmit] tx samples %d != %d\n",ret,nsamps); - } - - clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); - time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec); - if (time_min==0 ||loop==1 || time_min > time_diff) - time_min=time_diff; - if (time_max==0 ||loop==1 || time_max < time_diff) - time_max=time_diff; - if (time_avg ==0 ||loop==1) - time_avg= time_diff; - else - time_avg=(time_diff+time_avg) /2.0; - - /* //prints statics of uhd every 10 seconds - if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0) - LOG_I(HW,"usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg); - */ - loop++; - return ret; + s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); + s->tx_md.has_time_spec = flags; + + + if(flags>0) + s->tx_md.has_time_spec = true; + else + s->tx_md.has_time_spec = false; + + if (flags == 2) { // start of burst + s->tx_md.start_of_burst = true; + s->tx_md.end_of_burst = false; + } else if (flags == 3) { // end of burst + s->tx_md.start_of_burst = false; + s->tx_md.end_of_burst = true; + } else if (flags == 4) { // start and end + s->tx_md.start_of_burst = true; + s->tx_md.end_of_burst = true; + } else if (flags==1) { // middle of burst + s->tx_md.start_of_burst = false; + s->tx_md.end_of_burst = false; + } + + if (cc>1) { + std::vector<void *> buff_ptrs; + for (int i=0; i<cc; i++) + buff_ptrs.push_back(buff[i]); + ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3); + } else + ret = (int)s->tx_stream->send(buff[0], nsamps, s->tx_md,1e-3); + + + + if (ret != nsamps) + LOG_E(PHY,"[xmit] tx samples %d != %d\n",ret,nsamps); + + return ret; } /*! \brief Receive samples from hardware. @@ -243,621 +198,535 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, * \param antenna_id Index of antenna for which to receive samples * \returns the number of sample read */ -static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) -{ - static long long int loop=0; - static long time_min=0, time_max=0, time_avg=0; - struct timespec tp_start, tp_end; - long time_diff; - clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start); - usrp_state_t *s = (usrp_state_t*)device->priv; - int samples_received=0,i,j; - int nsamps2; // aligned to upper 32 or 16 byte boundary +static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + usrp_state_t *s = (usrp_state_t*)device->priv; + int samples_received=0,i,j; + int nsamps2; // aligned to upper 32 or 16 byte boundary #if defined(__x86_64) || defined(__i386__) #ifdef __AVX2__ - nsamps2 = (nsamps+7)>>3; - __m256i buff_tmp[2][nsamps2]; + nsamps2 = (nsamps+7)>>3; + __m256i buff_tmp[2][nsamps2]; #else - nsamps2 = (nsamps+3)>>2; - __m128i buff_tmp[2][nsamps2]; + nsamps2 = (nsamps+3)>>2; + __m128i buff_tmp[2][nsamps2]; #endif #elif defined(__arm__) - nsamps2 = (nsamps+3)>>2; - int16x8_t buff_tmp[2][nsamps2]; + nsamps2 = (nsamps+3)>>2; + int16x8_t buff_tmp[2][nsamps2]; #endif - - if (device->type == USRP_B200_DEV) { - if (cc>1) { - // receive multiple channels (e.g. RF A and RF B) - std::vector<void *> buff_ptrs; - - for (int i=0;i<cc;i++) buff_ptrs.push_back(buff_tmp[i]); - samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); - } else { - // receive a single channel (e.g. from connector RF A) - samples_received = s->rx_stream->recv(buff_tmp[0], nsamps, s->rx_md); - } - - // bring RX data into 12 LSBs for softmodem RX - for (int i=0;i<cc;i++) { - for (int j=0; j<nsamps2; j++) { + if (device->type == USRP_B200_DEV) { + if (cc>1) { + // receive multiple channels (e.g. RF A and RF B) + std::vector<void *> buff_ptrs; + for (int i=0; i<cc; i++) buff_ptrs.push_back(buff_tmp[i]); + samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); + } else { + // receive a single channel (e.g. from connector RF A) + samples_received=0; + while (samples_received != nsamps) { + samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received, + nsamps-samples_received, s->rx_md); + if (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE) + break; + } + } + // bring RX data into 12 LSBs for softmodem RX + for (int i=0; i<cc; i++) { + for (int j=0; j<nsamps2; j++) { #if defined(__x86_64__) || defined(__i386__) #ifdef __AVX2__ - ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4); + ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4); #else - ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4); + ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4); #endif #elif defined(__arm__) - ((int16x8_t*)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4); + ((int16x8_t*)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4); #endif - } + } + } + } else if (device->type == USRP_X300_DEV) { + if (cc>1) { + // receive multiple channels (e.g. RF A and RF B) + std::vector<void *> buff_ptrs; + + for (int i=0; i<cc; i++) buff_ptrs.push_back(buff[i]); + samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); + } else { + // receive a single channel (e.g. from connector RF A) + samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md); + } } - } else if (device->type == USRP_X300_DEV) { - if (cc>1) { - // receive multiple channels (e.g. RF A and RF B) - std::vector<void *> buff_ptrs; - - for (int i=0;i<cc;i++) buff_ptrs.push_back(buff[i]); - samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); - } else { - // receive a single channel (e.g. from connector RF A) - samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md); - } - } - - if (samples_received < nsamps) { - printf("[recv] received %d samples out of %d\n",samples_received,nsamps); - - } - - //handle the error code - switch(s->rx_md.error_code){ - case uhd::rx_metadata_t::ERROR_CODE_NONE: - break; - case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: - printf("[recv] USRP RX OVERFLOW!\n"); - s->num_overflows++; - break; - case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: - printf("[recv] USRP RX TIMEOUT!\n"); - break; - default: - printf("[recv] Unexpected error on RX, Error code: 0x%x\n",s->rx_md.error_code); - break; - } - s->rx_count += nsamps; - s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); - *ptimestamp = s->rx_timestamp; - - clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); - time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec); - if (time_min==0 ||loop==1 || time_min > time_diff) - time_min=time_diff; - if (time_max==0 ||loop==1 || time_max < time_diff) - time_max=time_diff; - if (time_avg ==0 ||loop==1) - time_avg= time_diff; - else - time_avg=(time_diff+time_avg) /2.0; - /* - //prints statics of uhd every 10 seconds - if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0) - LOG_I(HW,"usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg); - - loop++;*/ - return samples_received; -} + if (samples_received < nsamps) + LOG_E(PHY,"[recv] received %d samples out of %d\n",samples_received,nsamps); -/*! \brief Get current timestamp of USRP - * \param device the hardware to use -*/ -openair0_timestamp get_usrp_time(openair0_device *device) -{ - - usrp_state_t *s = (usrp_state_t*)device->priv; - - return s->usrp->get_time_now().to_ticks(s->sample_rate); -} + if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) + LOG_E(PHY, "%s\n", s->rx_md.to_pp_string(true).c_str()); + + s->rx_count += nsamps; + s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); + *ptimestamp = s->rx_timestamp; + return samples_received; +} /*! \brief Compares two variables within precision * \param a first variable * \param b second variable */ -static bool is_equal(double a, double b) -{ - return std::fabs(a-b) < std::numeric_limits<double>::epsilon(); +static bool is_equal(double a, double b) { + return std::fabs(a-b) < std::numeric_limits<double>::epsilon(); } void *freq_thread(void *arg) { - - openair0_device *device=(openair0_device *)arg; - usrp_state_t *s = (usrp_state_t*)device->priv; - - s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); - s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]); + + openair0_device *device=(openair0_device *)arg; + usrp_state_t *s = (usrp_state_t*)device->priv; + + s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); + s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]); } /*! \brief Set frequencies (TX/RX). Spawns a thread to handle the frequency change to not block the calling thread * \param device the hardware to use * \param openair0_cfg RF frontend parameters set by application * \param dummy dummy variable not used - * \returns 0 in success + * \returns 0 in success */ int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dont_block) { - usrp_state_t *s = (usrp_state_t*)device->priv; - pthread_t f_thread; + usrp_state_t *s = (usrp_state_t*)device->priv; + pthread_t f_thread; - printf("Setting USRP TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]); + printf("Setting USRP TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]); - // spawn a thread to handle the frequency change to not block the calling thread - if (dont_block == 1) - pthread_create(&f_thread,NULL,freq_thread,(void*)device); - else { - s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); - s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]); - } + // spawn a thread to handle the frequency change to not block the calling thread + if (dont_block == 1) + pthread_create(&f_thread,NULL,freq_thread,(void*)device); + else { + s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); + s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]); + } + + return(0); - return(0); - } -/*! \brief Set RX frequencies +/*! \brief Set RX frequencies * \param device the hardware to use * \param openair0_cfg RF frontend parameters set by application - * \returns 0 in success + * \returns 0 in success */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) { - usrp_state_t *s = (usrp_state_t*)device->priv; - static int first_call=1; - static double rf_freq,diff; + usrp_state_t *s = (usrp_state_t*)device->priv; + static int first_call=1; + static double rf_freq,diff; + + uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]); - uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]); + rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL; + rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0]; + rf_freq=openair0_cfg[0].rx_freq[0]; + s->usrp->set_rx_freq(rx_tune_req); - rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL; - rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0]; - rf_freq=openair0_cfg[0].rx_freq[0]; - s->usrp->set_rx_freq(rx_tune_req); + return(0); - return(0); - } /*! \brief Set Gains (TX/RX) * \param device the hardware to use * \param openair0_cfg RF frontend parameters set by application - * \returns 0 in success + * \returns 0 in success */ -int trx_usrp_set_gains(openair0_device* device, - openair0_config_t *openair0_cfg) { - - usrp_state_t *s = (usrp_state_t*)device->priv; - - s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]); - ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0); - // limit to maximum gain - if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) { - - printf("RX Gain 0 too high, reduce by %f dB\n", - openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] - gain_range.stop()); - exit(-1); - } - s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]); - printf("Setting USRP RX gain to %f (rx_gain %f,gain_range.stop() %f)\n", openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0],openair0_cfg[0].rx_gain[0],gain_range.stop()); - - return(0); +int trx_usrp_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) { + + usrp_state_t *s = (usrp_state_t*)device->priv; + + s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]); + ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0); + // limit to maximum gain + if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) { + LOG_E(PHY,"RX Gain 0 too high, reduce by %f dB\n", + openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] - gain_range.stop()); + exit(-1); + } + s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]); + LOG_I(PHY,"Setting USRP RX gain to %f (rx_gain %f,gain_range.stop() %f)\n", + openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0], + openair0_cfg[0].rx_gain[0],gain_range.stop()); + + return(0); } /*! \brief Stop USRP * \param card refers to the hardware index to use */ int trx_usrp_stop(openair0_device* device) { - return(0); + return(0); } /*! \brief USRPB210 RX calibration table */ rx_gain_calib_table_t calib_table_b210[] = { - {3500000000.0,44.0}, - {2660000000.0,49.0}, - {2300000000.0,50.0}, - {1880000000.0,53.0}, - {816000000.0,58.0}, - {-1,0}}; + {3500000000.0,44.0}, + {2660000000.0,49.0}, + {2300000000.0,50.0}, + {1880000000.0,53.0}, + {816000000.0,58.0}, + {-1,0} +}; /*! \brief USRPB210 RX calibration table */ rx_gain_calib_table_t calib_table_b210_38[] = { - {3500000000.0,44.0}, - {2660000000.0,49.8}, - {2300000000.0,51.0}, - {1880000000.0,53.0}, - {816000000.0,57.0}, - {-1,0}}; + {3500000000.0,44.0}, + {2660000000.0,49.8}, + {2300000000.0,51.0}, + {1880000000.0,53.0}, + {816000000.0,57.0}, + {-1,0} +}; /*! \brief USRPx310 RX calibration table */ rx_gain_calib_table_t calib_table_x310[] = { - {3500000000.0,77.0}, - {2660000000.0,81.0}, - {2300000000.0,81.0}, - {1880000000.0,82.0}, - {816000000.0,85.0}, - {-1,0}}; - -/*! \brief Set RX gain offset + {3500000000.0,77.0}, + {2660000000.0,81.0}, + {2300000000.0,81.0}, + {1880000000.0,82.0}, + {816000000.0,85.0}, + {-1,0} +}; + +/*! \brief Set RX gain offset * \param openair0_cfg RF frontend parameters set by application * \param chain_index RF chain to apply settings to - * \returns 0 in success + * \returns 0 in success */ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) { - int i=0; - // loop through calibration table to find best adjustment factor for RX frequency - double min_diff = 6e9,diff,gain_adj=0.0; - if (bw_gain_adjust==1) { - switch ((int)openair0_cfg[0].sample_rate) { - case 30720000: - break; - case 23040000: - gain_adj=1.25; - break; - case 15360000: - gain_adj=3.0; - break; - case 7680000: - gain_adj=6.0; - break; - case 3840000: - gain_adj=9.0; - break; - case 1920000: - gain_adj=12.0; - break; - default: - printf("unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); - exit(-1); - break; + int i=0; + // loop through calibration table to find best adjustment factor for RX frequency + double min_diff = 6e9,diff,gain_adj=0.0; + if (bw_gain_adjust==1) { + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + break; + case 23040000: + gain_adj=1.25; + break; + case 15360000: + gain_adj=3.0; + break; + case 7680000: + gain_adj=6.0; + break; + case 3840000: + gain_adj=9.0; + break; + case 1920000: + gain_adj=12.0; + break; + default: + LOG_E(PHY,"unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); + exit(-1); + break; + } } - } - while (openair0_cfg->rx_gain_calib_table[i].freq>0) { - diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); - printf("cal %d: freq %f, offset %f, diff %f\n", - i, - openair0_cfg->rx_gain_calib_table[i].freq, - openair0_cfg->rx_gain_calib_table[i].offset,diff); - if (min_diff > diff) { - min_diff = diff; - openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj; + while (openair0_cfg->rx_gain_calib_table[i].freq>0) { + diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); + LOG_I(PHY,"cal %d: freq %f, offset %f, diff %f\n", + i, + openair0_cfg->rx_gain_calib_table[i].freq, + openair0_cfg->rx_gain_calib_table[i].offset,diff); + if (min_diff > diff) { + min_diff = diff; + openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj; + } + i++; } - i++; - } - } -/*! \brief print the USRP statistics +/*! \brief print the USRP statistics * \param device the hardware to use * \returns 0 on success */ int trx_usrp_get_stats(openair0_device* device) { - - return(0); - + return(0); } -/*! \brief Reset the USRP statistics -* \param device the hardware to use -* \returns 0 on success -*/ +/*! \brief Reset the USRP statistics + * \param device the hardware to use + * \returns 0 on success + */ int trx_usrp_reset_stats(openair0_device* device) { - - return(0); - + return(0); } - - extern "C" { -/*! \brief Initialize Openair USRP target. It returns 0 if OK -* \param device the hardware to use -* \param openair0_cfg RF frontend parameters set by application -*/ - int device_init(openair0_device* device, openair0_config_t *openair0_cfg) { - - uhd::set_thread_priority_safe(1.0); - usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t)); - memset(s, 0, sizeof(usrp_state_t)); - - // Initialize USRP device - - device->openair0_cfg = openair0_cfg; - - std::string args = "type=b200"; - - - uhd::device_addrs_t device_adds = uhd::device::find(args); - size_t i; - - int vers=0,subvers=0,subsubvers=0; - int bw_gain_adjust=0; - - sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); - - printf("Checking for USRPs : UHD %s (%d.%d.%d)\n",uhd::get_version_string().c_str(),vers,subvers,subsubvers); - - if(device_adds.size() == 0) - { - double usrp_master_clock = 184.32e6; - - std::string args = "type=x300"; - - // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate - args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); - -// args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; - - uhd::device_addrs_t device_adds = uhd::device::find(args); - - if(device_adds.size() == 0) - { - std::cerr<<"No USRP Device Found. " << std::endl; - free(s); - return -1; - - } - + /*! \brief Initialize Openair USRP target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ + int device_init(openair0_device* device, openair0_config_t *openair0_cfg) { + uhd::set_thread_priority_safe(1.0); + usrp_state_t *s = (usrp_state_t*)calloc(sizeof(usrp_state_t),1); + // Initialize USRP device + device->openair0_cfg = openair0_cfg; - printf("Found USRP X300\n"); - s->usrp = uhd::usrp::multi_usrp::make(args); - // s->usrp->set_rx_subdev_spec(rx_subdev); - // s->usrp->set_tx_subdev_spec(tx_subdev); + std::string args = "type=b200"; + uhd::device_addrs_t device_adds = uhd::device::find(args); - // lock mboard clocks - if (openair0_cfg[0].clock_source == internal) - s->usrp->set_clock_source("internal"); - else - s->usrp->set_clock_source("external"); - - //Setting device type to USRP X300/X310 - device->type=USRP_X300_DEV; - - // this is not working yet, master clock has to be set via constructor - // set master clock rate and sample rate for tx & rx for streaming - //s->usrp->set_master_clock_rate(usrp_master_clock); - - openair0_cfg[0].rx_gain_calib_table = calib_table_x310; - - switch ((int)openair0_cfg[0].sample_rate) { - case 30720000: - // from usrp_time_offset - //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 15; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - break; - case 15360000: - //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 45; - openair0_cfg[0].tx_bw = 10e6; - openair0_cfg[0].rx_bw = 10e6; - break; - case 7680000: - //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 50; - openair0_cfg[0].tx_bw = 5e6; - openair0_cfg[0].rx_bw = 5e6; - break; - case 1920000: - //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 50; - openair0_cfg[0].tx_bw = 1.25e6; - openair0_cfg[0].rx_bw = 1.25e6; - break; - default: - printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); - exit(-1); - break; - } + int vers=0,subvers=0,subsubvers=0; + int bw_gain_adjust=0; - } else { - printf("Found USRP B200"); - args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=15360, recv_frame_size=15360" ; - s->usrp = uhd::usrp::multi_usrp::make(args); - - // s->usrp->set_rx_subdev_spec(rx_subdev); - // s->usrp->set_tx_subdev_spec(tx_subdev); - - // do not explicitly set the clock to "internal", because this will disable the gpsdo - // // lock mboard clocks - // s->usrp->set_clock_source("internal"); - // set master clock rate and sample rate for tx & rx for streaming - - // lock mboard clocks - if (openair0_cfg[0].clock_source == internal) - s->usrp->set_clock_source("internal"); - else - s->usrp->set_clock_source("external"); + sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); + LOG_I(PHY,"Checking for USRPs : UHD %s (%d.%d.%d)\n", + uhd::get_version_string().c_str(),vers,subvers,subsubvers); - device->type = USRP_B200_DEV; + if(device_adds.size() == 0) { + double usrp_master_clock = 184.32e6; + std::string args = "type=x300"; + // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate + args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); - if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { - openair0_cfg[0].rx_gain_calib_table = calib_table_b210; - bw_gain_adjust=0; - } - else { - openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38; - bw_gain_adjust=1; - } +// args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; - switch ((int)openair0_cfg[0].sample_rate) { - case 30720000: - s->usrp->set_master_clock_rate(30.72e6); - //openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 115; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - break; - case 23040000: - s->usrp->set_master_clock_rate(23.04e6); //to be checked - //openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 113; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - break; - case 15360000: - s->usrp->set_master_clock_rate(30.72e06); - //openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 103; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - break; - case 7680000: - s->usrp->set_master_clock_rate(30.72e6); - //openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 80; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - break; - case 1920000: - s->usrp->set_master_clock_rate(30.72e6); - //openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 40; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - break; - default: - printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); - exit(-1); - break; - } - } - - /* device specific */ - //openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered - //openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered - openair0_cfg[0].iq_txshift = 4;//shift - openair0_cfg[0].iq_rxrescale = 15;//rescale iqs - - for(i=0;i<s->usrp->get_rx_num_channels();i++) { - if (i<openair0_cfg[0].rx_num_channels) { - s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i); - //s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); - //printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); - s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); - set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); - - ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); - // limit to maximum gain - if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) { + // args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; + uhd::device_addrs_t device_adds = uhd::device::find(args); + + if(device_adds.size() == 0) { + std::cerr<<"No USRP Device Found. " << std::endl; + free(s); + return -1; + } + LOG_I(PHY,"Found USRP X300\n"); + s->usrp = uhd::usrp::multi_usrp::make(args); + // lock mboard clocks + if (openair0_cfg[0].clock_source == internal) + s->usrp->set_clock_source("internal"); + else + s->usrp->set_clock_source("external"); + + //Setting device type to USRP X300/X310 + device->type=USRP_X300_DEV; + + // this is not working yet, master clock has to be set via constructor + // set master clock rate and sample rate for tx & rx for streaming + //s->usrp->set_master_clock_rate(usrp_master_clock); + + openair0_cfg[0].rx_gain_calib_table = calib_table_x310; + + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + // from usrp_time_offset + //openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 15; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + break; + case 15360000: + //openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 45; + openair0_cfg[0].tx_bw = 10e6; + openair0_cfg[0].rx_bw = 10e6; + break; + case 7680000: + //openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 5e6; + openair0_cfg[0].rx_bw = 5e6; + break; + case 1920000: + //openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 1.25e6; + openair0_cfg[0].rx_bw = 1.25e6; + break; + default: + LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); + exit(-1); + break; + } + + } else { + LOG_I(PHY,"Found USRP B200\n"); + args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=15360, recv_frame_size=15360" ; + s->usrp = uhd::usrp::multi_usrp::make(args); + + // s->usrp->set_rx_subdev_spec(rx_subdev); + // s->usrp->set_tx_subdev_spec(tx_subdev); + + // do not explicitly set the clock to "internal", because this will disable the gpsdo + // // lock mboard clocks + // s->usrp->set_clock_source("internal"); + // set master clock rate and sample rate for tx & rx for streaming + + // lock mboard clocks + if (openair0_cfg[0].clock_source == internal) + s->usrp->set_clock_source("internal"); + else + s->usrp->set_clock_source("external"); + + device->type = USRP_B200_DEV; + if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { + openair0_cfg[0].rx_gain_calib_table = calib_table_b210; + bw_gain_adjust=0; + } else { + openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38; + bw_gain_adjust=1; + } + + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + s->usrp->set_master_clock_rate(30.72e6); + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 115; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + break; + case 23040000: + s->usrp->set_master_clock_rate(23.04e6); //to be checked + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 113; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + break; + case 15360000: + s->usrp->set_master_clock_rate(30.72e06); + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 103; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + break; + case 7680000: + s->usrp->set_master_clock_rate(30.72e6); + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 80; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + break; + case 1920000: + s->usrp->set_master_clock_rate(30.72e6); + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 40; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + break; + default: + LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); + exit(-1); + break; + } + } + + /* device specific */ + //openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered + //openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered + openair0_cfg[0].iq_txshift = 4;//shift + openair0_cfg[0].iq_rxrescale = 15;//rescale iqs + + for(int i=0; i<s->usrp->get_rx_num_channels(); i++) { + if (i<openair0_cfg[0].rx_num_channels) { + s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i); + s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); + set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); + + ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); + // limit to maximum gain + AssertFatal( openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] <= gain_range.stop(), + "RX Gain too high, lower by %f dB\n", + openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop()); + s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i); + LOG_I(PHY,"RX Gain %d %f (%f) => %f (max %f)\n",i, + openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i], + openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop()); + } + } + for(int i=0; i<s->usrp->get_tx_num_channels(); i++) { + if (i<openair0_cfg[0].tx_num_channels) { + s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i); + s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); + s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i],i); + } + } + + //s->usrp->set_clock_source("external"); + //s->usrp->set_time_source("external"); + + // display USRP settings + LOG_I(PHY,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6); + sleep(1); + + // create tx & rx streamer + uhd::stream_args_t stream_args_rx("sc16", "sc16"); + int samples=openair0_cfg[0].sample_rate; + int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps(); + samples/=10000; + LOG_I(PHY,"RF board max packet size %u, size for 100µs jitter %d \n", max, samples); + if ( samples < max ) + stream_args_rx.args["spp"] = str(boost::format("%d") % samples ); + LOG_I(PHY,"rx_max_num_samps %zu\n", + s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps()); + + for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++) + stream_args_rx.channels.push_back(i); + s->rx_stream = s->usrp->get_rx_stream(stream_args_rx); - printf("RX Gain %lu too high, lower by %f dB\n",i,openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop()); - exit(-1); - } - s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i); - printf("RX Gain %lu %f (%f) => %f (max %f)\n",i, - openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i], - openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop()); - } - } - for(i=0;i<s->usrp->get_tx_num_channels();i++) { - if (i<openair0_cfg[0].tx_num_channels) { - s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i); - //s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); - //printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->usrp->get_tx_num_channels(),openair0_cfg[0].tx_bw/1e6,s->usrp->get_tx_bandwidth(i)/1e6); - s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); - s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i],i); - } - } - - - // display USRP settings - std::cout << boost::format("Actual master clock: %fMHz...") % (s->usrp->get_master_clock_rate()/1e6) << std::endl; - - sleep(1); - - // create tx & rx streamer - uhd::stream_args_t stream_args_rx("sc16", "sc16"); - int samples=openair0_cfg[0].sample_rate; - samples/=24000; - // stream_args_rx.args["spp"] = str(boost::format("%d") % samples); - - for (i = 0; i<openair0_cfg[0].rx_num_channels; i++) - stream_args_rx.channels.push_back(i); - s->rx_stream = s->usrp->get_rx_stream(stream_args_rx); - std::cout << boost::format("rx_max_num_samps %u") % (s->rx_stream->get_max_num_samps()) << std::endl; - //openair0_cfg[0].samples_per_packet = s->rx_stream->get_max_num_samps(); - - uhd::stream_args_t stream_args_tx("sc16", "sc16"); - //stream_args_tx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].tx_num_channels*openair0_cfg[0].samples_per_packet)); - for (i = 0; i<openair0_cfg[0].tx_num_channels; i++) - stream_args_tx.channels.push_back(i); - s->tx_stream = s->usrp->get_tx_stream(stream_args_tx); - std::cout << boost::format("tx_max_num_samps %u") % (s->tx_stream->get_max_num_samps()) << std::endl; - - - /* Setting TX/RX BW after streamers are created due to USRP calibration issue */ - for(i=0;i<s->usrp->get_tx_num_channels();i++) { - if (i<openair0_cfg[0].tx_num_channels) { - s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); - printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->usrp->get_tx_num_channels(),openair0_cfg[0].tx_bw/1e6,s->usrp->get_tx_bandwidth(i)/1e6); - } - } - for(i=0;i<s->usrp->get_rx_num_channels();i++) { - if (i<openair0_cfg[0].rx_num_channels) { - s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); - printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); - } - } - - s->usrp->set_time_now(uhd::time_spec_t(0.0)); - - - for (i=0;i<openair0_cfg[0].rx_num_channels;i++) { - if (i<openair0_cfg[0].rx_num_channels) { - printf("RX Channel %lu\n",i); - std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->usrp->get_rx_rate(i)/1e6) << std::endl; - std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->usrp->get_rx_freq(i)/1e9) << std::endl; - std::cout << boost::format("Actual RX gain: %f...") % (s->usrp->get_rx_gain(i)) << std::endl; - std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->usrp->get_rx_bandwidth(i)/1e6) << std::endl; - std::cout << boost::format("Actual RX antenna: %s...") % (s->usrp->get_rx_antenna(i)) << std::endl; - } - } - - for (i=0;i<openair0_cfg[0].tx_num_channels;i++) { - - if (i<openair0_cfg[0].tx_num_channels) { - printf("TX Channel %lu\n",i); - std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->usrp->get_tx_rate(i)/1e6) << std::endl; - std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->usrp->get_tx_freq(i)/1e9) << std::endl; - std::cout << boost::format("Actual TX gain: %f...") % (s->usrp->get_tx_gain(i)) << std::endl; - std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth(i)/1e6) << std::endl; - std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna(i)) << std::endl; + uhd::stream_args_t stream_args_tx("sc16", "sc16"); + for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++) + stream_args_tx.channels.push_back(i); + s->tx_stream = s->usrp->get_tx_stream(stream_args_tx); + + /* Setting TX/RX BW after streamers are created due to USRP calibration issue */ + for(int i=0; i<s->usrp->get_tx_num_channels() && i<openair0_cfg[0].tx_num_channels; i++) + s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); + + for(int i=0; i<s->usrp->get_rx_num_channels() && i<openair0_cfg[0].rx_num_channels; i++) + s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); + + s->usrp->set_time_now(uhd::time_spec_t(0.0)); + + for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) { + LOG_I(PHY,"RX Channel %d\n",i); + LOG_I(PHY," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i)/1e6); + LOG_I(PHY," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9); + LOG_I(PHY," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i)); + LOG_I(PHY," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6); + LOG_I(PHY," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str()); + } + + for (int i=0; i<openair0_cfg[0].tx_num_channels; i++) { + LOG_I(PHY,"TX Channel %d\n",i); + LOG_I(PHY," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i)/1e6); + LOG_I(PHY," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9); + LOG_I(PHY," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i)); + LOG_I(PHY," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6); + LOG_I(PHY," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str()); + } + + LOG_I(PHY,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs()); + + device->priv = s; + device->trx_start_func = trx_usrp_start; + device->trx_write_func = trx_usrp_write; + device->trx_read_func = trx_usrp_read; + device->trx_get_stats_func = trx_usrp_get_stats; + device->trx_reset_stats_func = trx_usrp_reset_stats; + device->trx_end_func = trx_usrp_end; + device->trx_stop_func = trx_usrp_stop; + device->trx_set_freq_func = trx_usrp_set_freq; + device->trx_set_gains_func = trx_usrp_set_gains; + device->openair0_cfg = openair0_cfg; + + s->sample_rate = openair0_cfg[0].sample_rate; + // TODO: + // init tx_forward_nsamps based usrp_time_offset ex + if(is_equal(s->sample_rate, (double)30.72e6)) + s->tx_forward_nsamps = 176; + if(is_equal(s->sample_rate, (double)15.36e6)) + s->tx_forward_nsamps = 90; + if(is_equal(s->sample_rate, (double)7.68e6)) + s->tx_forward_nsamps = 50; + return 0; } - } - - std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl; - - device->priv = s; - device->trx_start_func = trx_usrp_start; - device->trx_write_func = trx_usrp_write; - device->trx_read_func = trx_usrp_read; - device->trx_get_stats_func = trx_usrp_get_stats; - device->trx_reset_stats_func = trx_usrp_reset_stats; - device->trx_end_func = trx_usrp_end; - device->trx_stop_func = trx_usrp_stop; - device->trx_set_freq_func = trx_usrp_set_freq; - device->trx_set_gains_func = trx_usrp_set_gains; - device->openair0_cfg = openair0_cfg; - - s->sample_rate = openair0_cfg[0].sample_rate; - // TODO: - // init tx_forward_nsamps based usrp_time_offset ex - if(is_equal(s->sample_rate, (double)30.72e6)) - s->tx_forward_nsamps = 176; - if(is_equal(s->sample_rate, (double)15.36e6)) - s->tx_forward_nsamps = 90; - if(is_equal(s->sample_rate, (double)7.68e6)) - s->tx_forward_nsamps = 50; - return 0; - } } /*@}*/ diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index 9a1a14baebf4669d00937ba795a77c10695ac3dd..c28b9e839c4377755498fc5a1a87e5cef27b78b2 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -85,7 +85,10 @@ int create_tasks(uint32_t enb_nb, uint32_t ue_nb) # if defined(NAS_BUILT_IN_UE) if (ue_nb > 0) { - if (itti_create_task (TASK_NAS_UE, nas_ue_task, NULL) < 0) { + nas_user_container_t *users = calloc(1, sizeof(*users)); + if (users == NULL) abort(); + users->count = ue_nb; + if (itti_create_task (TASK_NAS_UE, nas_ue_task, users) < 0) { LOG_E(NAS, "Create task for NAS UE failed\n"); return -1; } diff --git a/targets/COMMON/openairinterface5g_limits.h b/targets/COMMON/openairinterface5g_limits.h new file mode 100644 index 0000000000000000000000000000000000000000..d5a3b7f61c10d97699879d8f90b9e6d7ce818e10 --- /dev/null +++ b/targets/COMMON/openairinterface5g_limits.h @@ -0,0 +1,30 @@ +#ifndef OPENAIRINTERFACE5G_LIMITS_H_ +#define OPENAIRINTERFACE5G_LIMITS_H_ + +#if defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_LMSSDR) +# define NUMBER_OF_eNB_MAX 1 +# define NUMBER_OF_UE_MAX 16 +# define NUMBER_OF_CONNECTED_eNB_MAX 3 +#else +# define NUMBER_OF_eNB_MAX 7 +# define NUMBER_OF_UE_MAX 20 +# define NUMBER_OF_CONNECTED_eNB_MAX 3 + +# if defined(STANDALONE) && STANDALONE==1 +# undef NUMBER_OF_eNB_MAX +# undef NUMBER_OF_UE_MAX +# define NUMBER_OF_eNB_MAX 3 +# define NUMBER_OF_UE_MAX 3 +# endif + +# if defined(LARGE_SCALE) && LARGE_SCALE +# undef NUMBER_OF_eNB_MAX +# undef NUMBER_OF_UE_MAX +# undef NUMBER_OF_CONNECTED_eNB_MAX +# define NUMBER_OF_eNB_MAX 2 +# define NUMBER_OF_UE_MAX 120 +# define NUMBER_OF_CONNECTED_eNB_MAX 1 // to save some memory +# endif +#endif + +#endif /* OPENAIRINTERFACE5G_LIMITS_H_ */ diff --git a/targets/COMMON/threads_t.h b/targets/COMMON/threads_t.h new file mode 100644 index 0000000000000000000000000000000000000000..c9ba9fea1a4bf97d2c0c8134fd404e541f330245 --- /dev/null +++ b/targets/COMMON/threads_t.h @@ -0,0 +1,10 @@ +#ifndef _THREADS_T_H_ +#define _THREADS_T_H_ + +typedef struct threads_s { + int iq; + int odd; + int even; +} threads_t; + +#endif /* _THREADS_T_H_ */ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.25PRB.lmssdr.conf similarity index 95% rename from targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf rename to targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.25PRB.lmssdr.conf index 266e5aae25bb3281f27ef9d074d7ede2a31bc98a..3315b953da2c065cb043b78a7fc63801c94eca15 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.25PRB.lmssdr.conf @@ -35,8 +35,8 @@ eNBs = Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 107; + tx_gain = 70; + rx_gain = 116; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -46,7 +46,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -17; + pdsch_referenceSignalPower = -30; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; @@ -64,9 +64,9 @@ eNBs = srs_ackNackST =; srs_MaxUpPts =;*/ - pusch_p0_Nominal = -90; + pusch_p0_Nominal = -96; pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; + pucch_p0_Nominal = -104; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf index b81ac861f616f8c844300f40cd15321226b815a5..1083aa382a47d2428945792ebc5d19be973a827b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf @@ -23,85 +23,89 @@ eNBs = component_carriers = ( { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 13; - downlink_frequency = 751000000L; - uplink_frequency_offset = 31000000; - Nid_cell = 0; - N_RB_DL = 50; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -20; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -90; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; - /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; - */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 20; + rx_gain = 100; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -30; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; } ); - srb1_parameters : { # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] @@ -131,7 +135,6 @@ eNBs = SCTP_OUTSTREAMS = 2; }; - ////////// MME parameters: mme_ip_address = ( { ipv4 = "127.0.0.3"; ipv6 = "192:168:30::17"; @@ -146,7 +149,7 @@ eNBs = ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; ENB_INTERFACE_NAME_FOR_S1U = "lo"; - ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.5/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.exmimo2.conf new file mode 100644 index 0000000000000000000000000000000000000000..68bd3a10ec5f704d69ab725d8ac39044afb113c3 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.exmimo2.conf @@ -0,0 +1,169 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "TDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2580000000L; + uplink_frequency_offset = 0; //-120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 2; + nb_antennas_rx = 2; + tx_gain = 10; //25; + rx_gain = 10; //20; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -26; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 0; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -108; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 2; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.70"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="debug"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="debug"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpb210.conf new file mode 100644 index 0000000000000000000000000000000000000000..a33c2eb41b5b449604f51010719766f7399a8125 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpb210.conf @@ -0,0 +1,175 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2580000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -24; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "ENABLE"; + srs_BandwidthConfig = 2; + srs_SubframeConfig = 7; + srs_ackNackST = "DISABLE"; + srs_MaxUpPts = "DISABLE"; + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.lmssdr.conf new file mode 100644 index 0000000000000000000000000000000000000000..00f875ec4e2a27e50e7c9625a39c34d57a8d8ff1 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.lmssdr.conf @@ -0,0 +1,174 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 7; + rx_gain = 116; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -34; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -104; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.148"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.150/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.150/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf index e12acef70340404256fb63ee2538fc7a1f97b130..2d0e0f3702d8a7c43a40392aa068220234419b8f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf @@ -39,8 +39,8 @@ eNBs = nb_antenna_ports = 1; nb_antennas_tx = 1; nb_antennas_rx = 1; - tx_gain = 100; - rx_gain = 111; + tx_gain = 20; + rx_gain = 116; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -30; + pdsch_referenceSignalPower = -35; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; @@ -136,7 +136,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "127.0.0.3"; + mme_ip_address = ( { ipv4 = "192.168.12.148"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -145,11 +145,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.150/24"; - ENB_INTERFACE_NAME_FOR_S1U = "lo"; - ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.5/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.150/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf deleted file mode 100644 index 4cd761645b3e339c9b4cff404e974352a5f1f832..0000000000000000000000000000000000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf +++ /dev/null @@ -1,192 +0,0 @@ -Active_eNBs = ( "eNB_Eurecom_LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB_Eurecom_LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = "1"; - - mobile_country_code = "208"; - - mobile_network_code = "93"; - - ////////// Physical parameters: - - component_carriers = ( - { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 50; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 60; - rx_gain = 111; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -85; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; -/* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; -*/ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -100; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.170"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - -rrh_gw_config = ( - { - local_if_name = "eth0"; - #remote_address = "169.254.10.158"; - #local_address = "169.254.8.15"; - remote_address = "74:d4:35:cc:88:45"; - local_address = "d4:be:d9:22:0a:ac"; - local_port = 50000; #for raw option local port must be the same to remote - remote_port = 50000; - rrh_gw_active = "yes"; - tr_preference = "raw"; - rf_preference = "lmssdr"; - iq_txshift = 0; - tx_sample_advance = 45; - tx_scheduling_advance = 8; - -} -); - - NETWORK_INTERFACES : - { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth6"; - - - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - } -); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf index 8db3e2304dfd2f05afeca060a4bbf9866543fb03..140d215b9cb680169243ca15f277f206b7e592bf 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf @@ -34,7 +34,7 @@ eNBs = downlink_frequency = 2680000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; - N_RB_DL = 50; + N_RB_DL = 25; Nid_cell_mbsfn = 0; nb_antenna_ports = 1; nb_antennas_tx = 1; @@ -62,7 +62,7 @@ eNBs = pusch_nDMRS1 = 0; phich_duration = "NORMAL"; phich_resource = "ONESIXTH"; - srs_enable = "ENABLE"; + srs_enable = "DISABLE"; srs_BandwidthConfig =2; srs_SubframeConfig =13; srs_ackNackST ="DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf deleted file mode 100644 index d912b1a10213a42d9332a00199e4c3c3a88df14b..0000000000000000000000000000000000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf +++ /dev/null @@ -1,176 +0,0 @@ -Active_eNBs = ( "eNB_Eurecom_LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB_Eurecom_LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = "1"; - - mobile_country_code = "208"; - - mobile_network_code = "92"; - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "eNodeB_3GPP"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 100; - rx_gain = 111; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -85; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; -/* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; -*/ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -100; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - - ue_TransmissionMode = 1; - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.170"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - NETWORK_INTERFACES : - { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - - } -); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf deleted file mode 100644 index 9b052bf7ba9a888bb1b26cc8f654191513524982..0000000000000000000000000000000000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf +++ /dev/null @@ -1,192 +0,0 @@ -Active_eNBs = ( "eNB_Eurecom_LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB_Eurecom_LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = "1"; - - mobile_country_code = "208"; - - mobile_network_code = "92"; - - ////////// Physical parameters: - - component_carriers = ( - { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 60; - rx_gain = 111; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -85; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; -/* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; -*/ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -100; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.170"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - -rrh_gw_config = ( - { - local_if_name = "eth0"; - #remote_address = "169.254.10.158"; - #local_address = "169.254.8.15"; - remote_address = "74:d4:35:cc:88:45"; - local_address = "d4:be:d9:22:0a:ac"; - local_port = 50000; #for raw option local port must be the same to remote - remote_port = 50000; - rrh_gw_active = "yes"; - tr_preference = "raw"; - rf_preference = "lmssdr"; - iq_txshift = 0; - tx_sample_advance = 70; - tx_scheduling_advance = 8; - -} -); - - NETWORK_INTERFACES : - { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth6"; - - - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - } -); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index 5ef5a4f50b6e653a75f1c817cc6eeba3804d9d97..d563f3af7e1b681e9e220b96e1098aefae47d6f9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "94"; + mobile_network_code = "92"; ////////// Physical parameters: @@ -63,10 +63,10 @@ eNBs = phich_duration = "NORMAL"; phich_resource = "ONESIXTH"; srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ + srs_BandwidthConfig = 2; + srs_SubframeConfig = 0; + srs_ackNackST = "DISABLE"; + srs_MaxUpPts = "DISABLE"; pusch_p0_Nominal = -90; pusch_alpha = "AL1"; @@ -137,7 +137,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.70"; + mme_ip_address = ( { ipv4 = "192.168.12.26"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -147,10 +147,10 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.147/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth1"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.147/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf index dbd2220cbc22686850f5edb525766842c30fd919..4a89eb86e453ae16b9539d7aa4c130597b2b5a6c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf @@ -31,7 +31,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; @@ -51,7 +51,7 @@ eNBs = pucch_nCS_AN = 0; pucch_n1_AN = 32; pdsch_referenceSignalPower = -24; - pdsch_p_b = 0; + pdsch_p_b = 1; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; pusch_hoppingMode = "interSubFrame"; @@ -68,9 +68,9 @@ eNBs = srs_ackNackST =; srs_MaxUpPts =;*/ - pusch_p0_Nominal = -90; + pusch_p0_Nominal = -100; pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; + pucch_p0_Nominal = -106; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; @@ -138,7 +138,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.171"; + mme_ip_address = ( { ipv4 = "192.168.12.70"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -148,10 +148,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.150/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.150/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5-ercom.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5-ercom.conf index 1afa860c16366d7d46632f5b6424902061bfcbb3..ca17b85c0b926bb9ef5b04a4d95c0a2f36cbd813 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5-ercom.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5-ercom.conf @@ -254,6 +254,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; }, //second config for Ercom { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.conf index e52a36542fc005d63bf8ccfa91724d895f476172..f16fc611bee322f6198b347571c3a077d9444f2e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.conf @@ -166,7 +166,8 @@ eNBs = rf_preference = "usrp_b200"; iq_txshift = 4; tx_sample_advance = 80; - tx_scheduling_advance = 9; + tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.usrpb210.conf index cdaf13e01a6c0aa5d0d676069e1f550a70f20f19..446b3ceea3e72c13650a4ed80223d98e77621937 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.100PRB.usrpb210.conf @@ -168,6 +168,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.lo.conf index 5aad9973bb01be60aaf061dc896c08d18725811a..0ebb1d13fcaf6b18aa89a7d975647101b1f47c78 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.lo.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.lo.conf @@ -167,6 +167,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.usrpb210.conf index 8572fc69175e8fce82a5144d495b5c108aa54129..4990ee808f95ec5de660b40abc115021145a85e0 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.usrpb210.conf @@ -167,6 +167,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf index 918e7825cc4cefb0cba5327a07cb02dd0179a50b..fc51979ffa23653b85b2816ee4707685891f0710 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf @@ -167,6 +167,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.usrpb210.conf index 43385eefb974f235594eb0336ad674e908614f24..1e5b618673c908fcd6b0dc9ec5e40eab8c6a6fb6 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.usrpb210.conf @@ -168,6 +168,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.100PRB.usrpb210.conf index ee2b1cb021f7ee64a6989e3f3bc129d0e39c2b21..4b785da4e53ea1d5bfc33efeab98230da20630c0 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.100PRB.usrpb210.conf @@ -170,7 +170,8 @@ eNBs = rf_preference = "usrp_b200"; iq_txshift = 4; tx_sample_advance = 80; - tx_scheduling_advance = 9; + tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.usrpb210.conf index 7541fa1ee14abc9beab14d1bec662397867b191e..c261d4a2fc09a8e529d8fe677b90abdf6c7d6003 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.usrpb210.conf @@ -167,6 +167,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.50PRB.usrpb210.conf index 1044726c265738f2081f05e00923c469479cfde2..bca8e4e3ad1ff8c2b8ca5f8dcc32d11567dce716 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.50PRB.usrpb210.conf @@ -171,6 +171,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf index 868e499de6c58ede3ed14487d95d81c1e6ed18f2..4f0fdd1e3b3ba072bb66475e28e59fc30698f8d5 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf @@ -167,7 +167,8 @@ eNBs = rf_preference = "usrp_b200"; iq_txshift = 4; tx_sample_advance = 80; - tx_scheduling_advance = 9; + tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf index 9692f6bae06fd3acb0d4b070e324b646e7fa137c..2c5ae24c8c8b08e01d2660366aa34b7b3fce9982 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf @@ -166,7 +166,8 @@ eNBs = rf_preference = "usrp_b200"; iq_txshift = 4; tx_sample_advance = 80; - tx_scheduling_advance = 9; + tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf index aa731c8d8a23ee2e269682c3ccf3f2fc522b31e3..97351b9a6e7b8c7a57728967b493c9a84f53a368 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf @@ -169,6 +169,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.oaisim.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.oaisim.conf index 26ecfb64f2b23b25d6d87abca1cee28c1789aa52..bcb5c5f238ae449fec0c810208c5388b629828d8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.oaisim.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.oaisim.conf @@ -169,6 +169,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.usrpb210.conf index c97b215c77bc10e3a4305a2c33c3f02c49f99d2f..3ed4bb5884731b7305361f7685bf7f0172f4903f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.25PRB.usrpb210.conf @@ -169,6 +169,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.oaisim.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.oaisim.conf index b6cd51ec965f7b01af0f3557f596e4e4f61d7018..c728ad6b0cad50c07b158cf0d8909aab16a77207 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.oaisim.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.oaisim.conf @@ -169,6 +169,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210-conga.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210-conga.conf index 7f490f0ad3d68d76339aaef2578ee80ac447ed7b..58bf27945d557002b225ff928357ca4b118aa17f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210-conga.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210-conga.conf @@ -168,6 +168,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf index d40b9017856958d26ed6d9a408ec059a0b7fa778..f1179ebd2f0693fe5f7aafd846916f174ab640e7 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf @@ -169,6 +169,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf index 77b60349208a7e17c556d7a23d17db55cb6de780..c523188338ef6d76f4d332139655f9fcc684afe9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf @@ -167,6 +167,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.100PRB.usrpb210.conf index f6bbe9ff58a08e46b04b8ca2f4cce10f996d25de..da88c88e0b2e6f1d06c2c33b3193c3e2ea3e23d4 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.100PRB.usrpb210.conf @@ -166,6 +166,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.25PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.25PRB.usrpb210.conf index 71e435e2f41a34c16655417eb3444d9c6f038f6a..e7207edd493a0f78f4546de65275e85eb3ee9d16 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.25PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.25PRB.usrpb210.conf @@ -169,6 +169,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.50PRB.usrpb210.conf index 6c309df4db831ceca7394635cf30a28f4442e416..1ab0b8d486a59973a36a5d25fce0f1c044b8e5b8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.50PRB.usrpb210.conf @@ -166,6 +166,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf index 805bb1aba874380f0d99f5f11e3e26310e2c596d..7c0a846654a287f139ef9e654144206e015b992b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf @@ -168,6 +168,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf index dac1608948ae02d42992602b5fbce3d668690ff2..61885a5e061e3262508b9607abe3965d204cb619 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf @@ -167,6 +167,7 @@ eNBs = iq_txshift = 4; tx_sample_advance = 80; tx_scheduling_advance = 9; + if_compression = "alaw"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/start_enb_and_ue_virt.bash b/targets/PROJECTS/GENERIC-LTE-EPC/start_enb_and_ue_virt.bash index 5339af13e490f9f94aff25a537ff68ee1a92ff5f..6ea2d5bb0afe0efc6d64bc08b06b5e1c503b45bc 100755 --- a/targets/PROJECTS/GENERIC-LTE-EPC/start_enb_and_ue_virt.bash +++ b/targets/PROJECTS/GENERIC-LTE-EPC/start_enb_and_ue_virt.bash @@ -125,18 +125,18 @@ if [ ! -f $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data ] || [ ! -f $OPENAIR3_DIR/NA fi echo_success "make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS -f Makefile PROCESS=UE all" make -f Makefile --debug=b --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS PROCESS=UE all - rm .ue.nvram - rm .usim.nvram + rm .ue.nvram0 + rm .usim.nvram0 touch /tmp/nas_cleaned fi -if [ ! -f .ue.nvram ]; then - echo_success "generate .ue_emm.nvram .ue.nvram" +if [ ! -f .ue.nvram0 ]; then + echo_success "generate .ue_emm.nvram0 .ue.nvram0" $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --gen fi -if [ ! -f .usim.nvram ]; then - echo_success "generate .usim.nvram" +if [ ! -f .usim.nvram0 ]; then + echo_success "generate .usim.nvram0" $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/usim_data --gen fi $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --print diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/start_ue.bash b/targets/PROJECTS/GENERIC-LTE-EPC/start_ue.bash index e6d96602e270b5fb3d46ceddcd0291c1916df82c..ff16e27982a0e42954149bab6d3dbbf938bbf1f2 100755 --- a/targets/PROJECTS/GENERIC-LTE-EPC/start_ue.bash +++ b/targets/PROJECTS/GENERIC-LTE-EPC/start_ue.bash @@ -68,20 +68,20 @@ export NVRAM_DIR=$THIS_SCRIPT_PATH if [ ! -f $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data ]; then make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS veryveryclean make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS PROCESS=UE - rm .ue.nvram + rm .ue.nvram0 fi if [ ! -f $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/usim_data ]; then make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS veryveryclean make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS PROCESS=UE - rm .usim.nvram + rm .usim.nvram0 fi -if [ ! -f .ue.nvram ]; then - # generate .ue_emm.nvram .ue.nvram +if [ ! -f .ue.nvram0 ]; then + # generate .ue_emm.nvram0 .ue.nvram0 $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --gen fi -if [ ! -f .usim.nvram ]; then - # generate .usim.nvram +if [ ! -f .usim.nvram0 ]; then + # generate .usim.nvram0 $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/usim_data --gen fi $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --print diff --git a/targets/RT/USER/UE_transport_IQ.c b/targets/RT/USER/UE_transport_IQ.c index 8bbb78b4a3979fdd669a7e70ce0fd75d59db785b..05dd2bbf798e64c276856d7313cc29911075f5d9 100644 --- a/targets/RT/USER/UE_transport_IQ.c +++ b/targets/RT/USER/UE_transport_IQ.c @@ -87,7 +87,6 @@ void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag) { int i; int error_code_UE, error_code_proc_UE; - void *tmp; RT_flag_UE=RT_flag; NRT_flag_UE=NRT_flag; @@ -245,8 +244,7 @@ void *rrh_UE_thread(void *arg) { struct sched_param sched_param_UE_rx, sched_param_UE_tx; int16_t i,cmd; //,nsamps,antenna_index; - ssize_t bytes_received; - struct timespec time_req_1us, time_rem_1us; + //struct timespec time_req_1us; pthread_t UE_rx_thread, UE_tx_thread; pthread_attr_t attr_UE_rx, attr_UE_tx; int error_code_UE_rx, error_code_UE_tx; @@ -254,8 +252,8 @@ void *rrh_UE_thread(void *arg) { unsigned int samples_per_frame=0; samples_per_frame= dev->eth_dev.openair0_cfg->samples_per_frame; - time_req_1us.tv_sec = 0; - time_req_1us.tv_nsec = 1000; + //time_req_1us.tv_sec = 0; + //time_req_1us.tv_nsec = 1000; while (rrh_exit==0) { @@ -338,12 +336,15 @@ void *rrh_UE_rx_thread(void *arg) { int trace_cnt=0; unsigned long long max_rx_time=0, min_rx_time=133333, total_rx_time=0, average_rx_time=133333, s_period=0, trial=0; unsigned int samples_per_frame=0; - openair0_timestamp temp, last_hw_counter=0; + openair0_timestamp last_hw_counter=0; antenna_index = 0; nsamps = dev->eth_dev.openair0_cfg->samples_per_packet; samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame; + /* TODO: check if setting time0 has to be done here */ + clock_gettime(CLOCK_MONOTONIC,&time0); + while (rrh_exit == 0) { if (!UE_rx_started) { UE_rx_started=1; //Set this flag to 1 to indicate that a UE started retrieving data @@ -446,7 +447,7 @@ void *rrh_UE_rx_thread(void *arg) { if (s_period++ == PRINTF_PERIOD) { s_period=0; - printf("Average UE RX time : %lu\tMax RX time : %lu\tMin RX time : %lu\n",average_rx_time,max_rx_time,min_rx_time); + printf("Average UE RX time : %llu\tMax RX time : %llu\tMin RX time : %llu\n",average_rx_time,max_rx_time,min_rx_time); } @@ -481,7 +482,6 @@ void *rrh_UE_tx_thread(void *arg) { rrh_module_t *dev = (rrh_module_t *)arg; ssize_t bytes_received; int antenna_index, nsamps; - int trace_cnt=0; unsigned int samples_per_frame=0; antenna_index = 0; @@ -504,7 +504,7 @@ void *rrh_UE_tx_thread(void *arg) { if (NRT_flag_UE==1) { nrt_UE_counter[antenna_index]++; } - printf(" first part size: %d second part size: %d idx=%d \n", + printf(" first part size: %d second part size: %"PRId64" idx=%"PRId64"\n", (int32_t)(((samples_per_frame)<<2)-((timestamp_UE_tx[antenna_index]%(samples_per_frame))<<2)), (nsamps<<2)-((samples_per_frame)<<2)+((timestamp_UE_tx[antenna_index]%(samples_per_frame))<<2), timestamp_UE_tx[antenna_index]%(samples_per_frame)); diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index fb351af6d638d2bbc9fb79e4d465260b759142bb..b57a201fb5f901417d919bbed85bdf919f6b51ff 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -539,13 +539,13 @@ void *rrh_eNB_rx_thread(void *arg) { void *rrh_eNB_tx_thread(void *arg) { - struct timespec time0a,time0,time1,time2; + struct timespec time0,time1,time2; rrh_module_t *dev = (rrh_module_t *)arg; struct timespec time_req_1us, time_rem_1us; ssize_t bytes_received; int i; - openair0_timestamp last_hw_counter=0; + //openair0_timestamp last_hw_counter=0; unsigned int samples_per_frame=0,samples_per_subframe=0; unsigned int spp_rf=0, spp_eth=0; uint8_t loopback=0,measurements=0; @@ -634,7 +634,7 @@ void *rrh_eNB_tx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_tx&0xffffffff ); - if (dev->devs->type == NONE_DEV) last_hw_counter=hw_counter; + //if (dev->devs->type == NONE_DEV) last_hw_counter=hw_counter; if (loopback ==1 ) { diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index d70352b4101c8285d9a8a31e7c72463aefbfbcc0..a3ecbeb9142467eaaae9f90fa5209fbd027dd8c6 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -45,6 +45,8 @@ #include <sys/sysinfo.h> #include "rt_wrapper.h" +#include "time_utils.h" + #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all #include "assertions.h" @@ -163,6 +165,14 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst void stop_eNB(int nb_inst); +static int recv_if_count = 0; +struct timespec start_rf_new, start_rf_prev, start_rf_prev2, end_rf; +openair0_timestamp start_rf_new_ts, start_rf_prev_ts, start_rf_prev2_ts, end_rf_ts; +extern struct timespec start_fh, start_fh_prev; +extern int start_fh_sf, start_fh_prev_sf; +struct timespec end_fh; +int end_fh_sf; + static inline void thread_top_init(char *thread_name, int affinity, uint64_t runtime, @@ -403,6 +413,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) } } } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); } @@ -675,17 +686,17 @@ void fh_if5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { proc->first_rx =2; *subframe = proc->subframe_rx; *frame = proc->frame_rx; - LOG_E(PHY,"[Mobipass]timestamp_rx:%llu, frame_rx %d, subframe: %d\n",proc->timestamp_rx,proc->frame_rx,proc->subframe_rx); + LOG_E(PHY,"[Mobipass]timestamp_rx:%"PRId64", frame_rx %d, subframe: %d\n",proc->timestamp_rx,proc->frame_rx,proc->subframe_rx); } else { if (proc->subframe_rx != *subframe) { proc->first_rx++; - LOG_E(PHY,"[Mobipass]timestamp:%llu, subframe_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx, proc->subframe_rx,*subframe, proc->first_rx); + LOG_E(PHY,"[Mobipass]timestamp:%"PRId64", subframe_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx, proc->subframe_rx,*subframe, proc->first_rx); //exit_fun("Exiting"); } if (proc->frame_rx != *frame) { proc->first_rx++; - LOG_E(PHY,"[Mobipass]timestamp:%llu, frame_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx); + LOG_E(PHY,"[Mobipass]timestamp:%"PRId64", frame_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx); // exit_fun("Exiting"); } // temporary solution @@ -749,13 +760,18 @@ void fh_if5_asynch_DL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { openair0_timestamp timestamp_tx; recv_IF5(eNB, ×tamp_tx, *subframe, IF5_RRH_GW_DL); - //printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); + clock_gettime( CLOCK_MONOTONIC, &end_fh); + end_fh_sf = *subframe; + recv_if_count = recv_if_count + 1; + LOG_D(HW,"[From SF %d to SF %d] RTT_FH: %"PRId64"\n", start_fh_prev_sf, end_fh_sf, clock_difftime_ns(start_fh_prev, end_fh)); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; frame_tx = (timestamp_tx/(fp->samples_per_tti*10))&1023; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB, subframe_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB, subframe_tx ); if (proc->first_tx != 0) { *subframe = subframe_tx; @@ -830,7 +846,7 @@ void fh_if4p5_asynch_DL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { exit_fun("Exiting"); } } while (proc->symbol_mask[*subframe] != symbol_mask_full); - + *frame = frame_tx; @@ -914,6 +930,7 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { // Transmit TX buffer based on timestamp from RX // printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers lte_subframe_t SF_type = subframe_select(fp,(proc->subframe_rx+tx_sfoffset)%10); @@ -951,7 +968,13 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { siglen, fp->nb_antennas_tx, flags); - + clock_gettime( CLOCK_MONOTONIC, &end_rf); + end_rf_ts = proc->timestamp_rx+eNB->ts_offset+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance; + if (recv_if_count != 0 ) { + recv_if_count = recv_if_count-1; + LOG_D(HW,"[From Timestamp %"PRId64" to Timestamp %"PRId64"] RTT_RF: %"PRId64"; RTT_RF\n", start_rf_prev_ts, end_rf_ts, clock_difftime_ns(start_rf_prev, end_rf)); + LOG_D(HW,"[From Timestamp %"PRId64" to Timestamp %"PRId64"] RTT_RF: %"PRId64"; RTT_RF\n",start_rf_prev2_ts, end_rf_ts, clock_difftime_ns(start_rf_prev2, end_rf)); + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); @@ -975,6 +998,14 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { rxp, fp->samples_per_tti, fp->nb_antennas_rx); + start_rf_prev2= start_rf_prev; + start_rf_prev2_ts= start_rf_prev_ts; + start_rf_prev = start_rf_new; + start_rf_prev_ts = start_rf_new_ts; + clock_gettime( CLOCK_MONOTONIC, &start_rf_new); + start_rf_new_ts = ts; + LOG_D(PHY,"rx_rf: first_rx %d received ts %"PRId64" (sptti %d)\n",proc->first_rx,ts,fp->samples_per_tti); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); proc->timestamp_rx = ts-eNB->ts_offset; @@ -990,7 +1021,7 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { else { if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { - LOG_I(PHY,"rx_rf: rfdevice timing drift of %d samples\n",proc->timestamp_rx - old_ts - fp->samples_per_tti); + LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,eNB->ts_offset); eNB->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); proc->timestamp_rx = ts-eNB->ts_offset; } @@ -1007,12 +1038,12 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { if (proc->first_rx == 0) { if (proc->subframe_rx != *subframe){ - LOG_E(PHY,"rx_rf: Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->timestamp_rx,proc->subframe_rx,*subframe); + LOG_E(PHY,"rx_rf: Received Timestamp (%"PRId64") doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->timestamp_rx,proc->subframe_rx,*subframe); exit_fun("Exiting"); } int f2 = (*frame+proc->frame_offset)&1023; if (proc->frame_rx != f2) { - LOG_E(PHY,"rx_rf: Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, frame_offset %d, f2 %d)\n",proc->timestamp_rx,proc->frame_rx,*frame,proc->frame_offset,f2); + LOG_E(PHY,"rx_rf: Received Timestamp (%"PRId64") doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, frame_offset %d, f2 %d)\n",proc->timestamp_rx,proc->frame_rx,*frame,proc->frame_offset,f2); exit_fun("Exiting"); } } else { @@ -1529,7 +1560,7 @@ static void* eNB_thread_single( void* param ) { wait_sync("eNB_thread_single"); #if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) - if (eNB->node_function < NGFI_RRU_IF5) + if ((eNB->node_function < NGFI_RRU_IF5) && (eNB->mac_enabled==1)) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif @@ -1631,8 +1662,8 @@ static void* eNB_thread_single( void* param ) { } if (eNB->CC_id==1) - LOG_D(PHY,"eNB thread single %p (proc %p, CC_id %d), frame %d (%p), subframe %d (%p)\n", - pthread_self(), proc, eNB->CC_id, frame,&frame,subframe,&subframe); + LOG_D(PHY,"eNB thread single (proc %p, CC_id %d), frame %d (%p), subframe %d (%p)\n", + proc, eNB->CC_id, frame,&frame,subframe,&subframe); // synchronization on FH interface, acquire signals/data and block if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe); @@ -2029,6 +2060,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst printf("Exiting, cannot initialize transport protocol\n"); exit(-1); } + malloc_IF5_buffer(eNB); break; case NGFI_RRU_IF4p5: eNB->do_precoding = 0; @@ -2118,6 +2150,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst printf("Exiting, cannot initialize transport protocol\n"); exit(-1); } + malloc_IF5_buffer(eNB); break; case NGFI_RCC_IF4p5: eNB->do_precoding = 0; @@ -2170,11 +2203,11 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst malloc_IF4p5_buffer(eNB); } - } - if (setup_eNB_buffers(PHY_vars_eNB_g[inst],&openair0_cfg[CC_id])!=0) { - printf("Exiting, cannot initialize eNodeB Buffers\n"); - exit(-1); + if (setup_eNB_buffers(PHY_vars_eNB_g[inst],&openair0_cfg[CC_id])!=0) { + printf("Exiting, cannot initialize eNodeB Buffers\n"); + exit(-1); + } } init_eNB_proc(inst); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 5342a1b665fbf5e0b94b474042d371c73d0bab36..68fcbc49d5eb2e88dec2d63221044b53c2b5505f 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -29,37 +29,13 @@ * \note * \warning */ -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <sched.h> -#include <linux/sched.h> -#include <signal.h> -#include <execinfo.h> -#include <getopt.h> -#include <sys/sysinfo.h> + +#include "lte-softmodem.h" #include "T.h" #include "rt_wrapper.h" -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all - -#include "assertions.h" -#include "msc.h" - -#include "PHY/types.h" - -#include "PHY/defs.h" -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all -//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all - -#include "../../ARCH/COMMON/common_lib.h" #include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all @@ -94,34 +70,15 @@ unsigned short config_frames[4] = {2,9,11,13}; #endif #if defined(ENABLE_ITTI) -# include "intertask_interface_init.h" -# include "create_tasks.h" -# if defined(ENABLE_USE_MME) -# include "s1ap_eNB.h" -#ifdef PDCP_USE_NETLINK -# include "SIMULATION/ETH_TRANSPORT/proto.h" -extern int netlink_init(void); -#endif -# endif +#include "intertask_interface_init.h" +#include "create_tasks.h" #endif +#include "system.h" + #ifdef XFORMS #include "PHY/TOOLS/lte_phy_scope.h" #include "stats.h" -#endif - -// In lte-enb.c -extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg); -extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int,int); -extern void stop_eNB(int); -extern void kill_eNB_proc(void); - -// In lte-ue.c -extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg); -extern void fill_ue_band_info(void); -extern void init_UE(int); - -#ifdef XFORMS // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) // at eNB 0, an UL scope for every UE FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX]; @@ -129,40 +86,24 @@ FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; char title[255]; unsigned char scope_enb_num_ue = 2; +static pthread_t forms_thread; //xforms #endif //XFORMS - - - - - pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; int sync_var=-1; //!< protected by mutex \ref sync_mutex. - - - - -#ifdef XFORMS -static pthread_t forms_thread; //xforms -#endif - uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] - #if defined(ENABLE_ITTI) volatile int start_eNB = 0; volatile int start_UE = 0; #endif volatile int oai_exit = 0; - - static clock_source_t clock_source = internal; - -static wait_for_sync = 0; +static int wait_for_sync = 0; static char UE_flag=0; unsigned int mmapped_dma=0; @@ -209,6 +150,8 @@ int chain_offset=0; int phy_test = 0; uint8_t usim_test = 0; +uint8_t nb_antenna_tx = 1; +uint8_t nb_antenna_rx = 1; char ref[128] = "internal"; char channels[128] = "0"; @@ -223,7 +166,6 @@ int otg_enabled; #endif //int number_of_cards = 1; - static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; eNB_func_t node_function[MAX_NUM_CCs]; eNB_timing_t node_timing[MAX_NUM_CCs]; @@ -235,9 +177,6 @@ uint32_t timing_advance = 0; uint8_t exit_missed_slots=1; uint64_t num_missed_slots=0; // counter for the number of missed slots - -extern void reset_opp_meas(void); -extern void print_opp_meas(void); int transmission_mode=1; int16_t glog_level = LOG_INFO; @@ -268,12 +207,9 @@ int16_t osa_log_level = LOG_INFO; int16_t osa_log_verbosity = LOG_MED; #endif - - char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; - /* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; /* struct for ethernet specific parameters given in eNB conf file */ @@ -286,75 +222,81 @@ double cpuf; char uecap_xer[1024],uecap_xer_in=0; int oaisim_flag=0; +threads_t threads= {-1,-1,-1}; + +/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed + * this is very hackish - find a proper solution + */ +uint8_t abstraction_flag=0; /*---------------------BMC: timespec helpers -----------------------------*/ struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; -struct timespec clock_difftime(struct timespec start, struct timespec end) -{ - struct timespec temp; - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - return temp; +struct timespec clock_difftime(struct timespec start, struct timespec end) { + struct timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; } -void print_difftimes(void) -{ +void print_difftimes(void) { #ifdef DEBUG - printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); + printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); #else - LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); + LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); #endif } -void update_difftimes(struct timespec start, struct timespec end) -{ - struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - int changed = 0; - diff_time = clock_difftime(start, end); - if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } - if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } +void update_difftimes(struct timespec start, struct timespec end) { + struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + int changed = 0; + diff_time = clock_difftime(start, end); + if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { + min_diff_time.tv_nsec = diff_time.tv_nsec; + changed = 1; + } + if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { + max_diff_time.tv_nsec = diff_time.tv_nsec; + changed = 1; + } #if 1 - if (changed) print_difftimes(); + if (changed) print_difftimes(); #endif } /*------------------------------------------------------------------------*/ -unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) -{ - return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); +unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { + return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); } -unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) -{ - return (dcoff_i_rxfe + (dcoff_q_rxfe<<8)); +unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) { + return (dcoff_i_rxfe + (dcoff_q_rxfe<<8)); } #if !defined(ENABLE_ITTI) -void signal_handler(int sig) -{ - void *array[10]; - size_t size; - - if (sig==SIGSEGV) { - // get void*'s for all entries on the stack - size = backtrace(array, 10); - - // print out all the frames to stderr - fprintf(stderr, "Error: signal %d:\n", sig); - backtrace_symbols_fd(array, size, 2); - exit(-1); - } else { - printf("trying to exit gracefully...\n"); - oai_exit = 1; - } +void signal_handler(int sig) { + void *array[10]; + size_t size; + + if (sig==SIGSEGV) { + // get void*'s for all entries on the stack + size = backtrace(array, 10); + + // print out all the frames to stderr + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, 2); + exit(-1); + } else { + printf("trying to exit gracefully...\n"); + oai_exit = 1; + } } #endif #define KNRM "\x1B[0m" @@ -379,12 +321,15 @@ void help (void) { printf(" --ue-rxgain set UE RX gain\n"); printf(" --ue-rxgain-off external UE amplifier offset\n"); printf(" --ue-txgain set UE TX gain\n"); - printf(" --ue-scan_carrier set UE to scan around carrier\n"); + printf(" --ue-nb-ant-rx set UE number of rx antennas\n"); + printf(" --ue-scan-carrier set UE to scan around carrier\n"); + printf(" --dlsch-demod-shift dynamic shift for LLR compuation for TM3/4 (default 0)\n"); printf(" --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n"); printf(" --mmapped-dma sets flag for improved EXMIMO UE performance\n"); printf(" --external-clock tells hardware to use an external clock reference\n"); printf(" --usim-test use XOR autentication algo in case of test usim mode\n"); printf(" --single-thread-disable. Disables single-thread mode in lte-softmodem\n"); + printf(" -A Set timing_advance\n"); printf(" -C Set the downlink frequency for all component carriers\n"); printf(" -d Enable soft scope and L1 and L2 stats (Xforms)\n"); printf(" -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"); @@ -405,40 +350,38 @@ void help (void) { printf(" -x Set the transmission mode, valid options: 1 \n"); printf(" -E Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"); #if T_TRACER - printf(" --T_port [port] use given port\n"); - printf(" --T_nowait don't wait for tracer, start immediately\n"); - printf(" --T_dont_fork to ease debugging with gdb\n"); + printf(" --T_port [port] use given port\n"); + printf(" --T_nowait don't wait for tracer, start immediately\n"); + printf(" --T_dont_fork to ease debugging with gdb\n"); #endif - printf(RESET); - fflush(stdout); + printf(RESET); + fflush(stdout); } -void exit_fun(const char* s) -{ - int CC_id; - - if (s != NULL) { - printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s); - } +void exit_fun(const char* s) { + int CC_id; - oai_exit = 1; - - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - if (UE_flag == 0) { - if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); - if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + if (s != NULL) { + printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s); } - else { - if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) - PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + + oai_exit = 1; + + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + if (UE_flag == 0) { + if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } else { + if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } } - } #if defined(ENABLE_ITTI) - sleep(1); //allow lte-softmodem threads to exit first - itti_terminate_tasks (TASK_UNKNOWN); + sleep(1); //allow lte-softmodem threads to exit first + itti_terminate_tasks (TASK_UNKNOWN); #endif } @@ -446,131 +389,129 @@ void exit_fun(const char* s) #ifdef XFORMS -void reset_stats(FL_OBJECT *button, long arg) -{ - int i,j,k; - PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0]; - - for (i=0; i<NUMBER_OF_UE_MAX; i++) { - for (k=0; k<8; k++) { //harq_processes - for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) { - phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; - phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; - phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; - } - - phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; - phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; - phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; +void reset_stats(FL_OBJECT *button, long arg) { + int i,j,k; + PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0]; + + for (i=0; i<NUMBER_OF_UE_MAX; i++) { + for (k=0; k<8; k++) { //harq_processes + for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; + } + + phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; + + for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; + } + } - for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) { - phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; - phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; - phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; - phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; - } + phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; + phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; + phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; } - - phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; - phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; - phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; - } } -static void *scope_thread(void *arg) -{ - char stats_buffer[16384]; +static void *scope_thread(void *arg) { + char stats_buffer[16384]; # ifdef ENABLE_XFORMS_WRITE_STATS - FILE *UE_stats, *eNB_stats; + FILE *UE_stats, *eNB_stats; # endif - int len = 0; - struct sched_param sched_param; - int UE_id, CC_id; - int ue_cnt=0; + int len = 0; + struct sched_param sched_param; + int UE_id, CC_id; + int ue_cnt=0; - sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; - sched_setscheduler(0, SCHED_FIFO,&sched_param); + sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; + sched_setscheduler(0, SCHED_FIFO,&sched_param); - printf("Scope thread has priority %d\n",sched_param.sched_priority); + printf("Scope thread has priority %d\n",sched_param.sched_priority); # ifdef ENABLE_XFORMS_WRITE_STATS - if (UE_flag==1) - UE_stats = fopen("UE_stats.txt", "w"); - else - eNB_stats = fopen("eNB_stats.txt", "w"); + if (UE_flag==1) + UE_stats = fopen("UE_stats.txt", "w"); + else + eNB_stats = fopen("eNB_stats.txt", "w"); #endif - while (!oai_exit) { - if (UE_flag==1) { - len = dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm); - //fl_set_object_label(form_stats->stats_text, stats_buffer); - fl_clear_browser(form_stats->stats_text); - fl_add_browser_line(form_stats->stats_text, stats_buffer); + while (!oai_exit) { + if (UE_flag==1) { + len = dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm); + //fl_set_object_label(form_stats->stats_text, stats_buffer); + fl_clear_browser(form_stats->stats_text); + fl_add_browser_line(form_stats->stats_text, stats_buffer); - phy_scope_UE(form_ue[0], - PHY_vars_UE_g[0][0], - 0, - 0,7); + phy_scope_UE(form_ue[0], + PHY_vars_UE_g[0][0], + 0, + 0,7); - } else { - if (PHY_vars_eNB_g[0][0]->mac_enabled==1) { - len = dump_eNB_l2_stats (stats_buffer, 0); - //fl_set_object_label(form_stats_l2->stats_text, stats_buffer); - fl_clear_browser(form_stats_l2->stats_text); - fl_add_browser_line(form_stats_l2->stats_text, stats_buffer); - } - len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0); - - if (MAX_NUM_CCs>1) - len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0); - - //fl_set_object_label(form_stats->stats_text, stats_buffer); - fl_clear_browser(form_stats->stats_text); - fl_add_browser_line(form_stats->stats_text, stats_buffer); - - ue_cnt=0; - for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - // if ((PHY_vars_eNB_g[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) { - if ((ue_cnt<scope_enb_num_ue)) { - phy_scope_eNB(form_enb[CC_id][ue_cnt], - PHY_vars_eNB_g[0][CC_id], - UE_id); - ue_cnt++; - } - } - } + } else { + if (PHY_vars_eNB_g[0][0]->mac_enabled==1) { + len = dump_eNB_l2_stats (stats_buffer, 0); + //fl_set_object_label(form_stats_l2->stats_text, stats_buffer); + fl_clear_browser(form_stats_l2->stats_text); + fl_add_browser_line(form_stats_l2->stats_text, stats_buffer); + } + len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0); + + if (MAX_NUM_CCs>1) + len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0); + + //fl_set_object_label(form_stats->stats_text, stats_buffer); + fl_clear_browser(form_stats->stats_text); + fl_add_browser_line(form_stats->stats_text, stats_buffer); + + ue_cnt=0; + for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + // if ((PHY_vars_eNB_g[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) { + if ((ue_cnt<scope_enb_num_ue)) { + phy_scope_eNB(form_enb[CC_id][ue_cnt], + PHY_vars_eNB_g[0][CC_id], + UE_id); + ue_cnt++; + } + } + } - } + } - //printf("doing forms\n"); - //usleep(100000); // 100 ms - sleep(1); - } + //printf("doing forms\n"); + //usleep(100000); // 100 ms + sleep(1); + } - // printf("%s",stats_buffer); + // printf("%s",stats_buffer); # ifdef ENABLE_XFORMS_WRITE_STATS - if (UE_flag==1) { - if (UE_stats) { - rewind (UE_stats); - fwrite (stats_buffer, 1, len, UE_stats); - fclose (UE_stats); - } - } else { - if (eNB_stats) { - rewind (eNB_stats); - fwrite (stats_buffer, 1, len, eNB_stats); - fclose (eNB_stats); + if (UE_flag==1) { + if (UE_stats) { + rewind (UE_stats); + fwrite (stats_buffer, 1, len, UE_stats); + fclose (UE_stats); + } + } else { + if (eNB_stats) { + rewind (eNB_stats); + fwrite (stats_buffer, 1, len, eNB_stats); + fclose (eNB_stats); + } } - } # endif - pthread_exit((void*)arg); + pthread_exit((void*)arg); } #endif @@ -578,157 +519,167 @@ static void *scope_thread(void *arg) #if defined(ENABLE_ITTI) -void *l2l1_task(void *arg) -{ - MessageDef *message_p = NULL; - int result; +void *l2l1_task(void *arg) { + MessageDef *message_p = NULL; + int result; - itti_set_task_real_time(TASK_L2L1); - itti_mark_task_ready(TASK_L2L1); + itti_set_task_real_time(TASK_L2L1); + itti_mark_task_ready(TASK_L2L1); + + if (UE_flag == 0) { + /* Wait for the initialize message */ + printf("Wait for the ITTI initialize message\n"); + do { + if (message_p != NULL) { + result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } + + itti_receive_msg (TASK_L2L1, &message_p); + + switch (ITTI_MSG_ID(message_p)) { + case INITIALIZE_MESSAGE: + /* Start eNB thread */ + LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p)); + start_eNB = 1; + break; + + case TERMINATE_MESSAGE: + printf("received terminate message\n"); + oai_exit=1; + itti_exit_task (); + break; + + default: + LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); + break; + } + } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE); - if (UE_flag == 0) { - /* Wait for the initialize message */ - printf("Wait for the ITTI initialize message\n"); - do { - if (message_p != NULL) { result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } - - itti_receive_msg (TASK_L2L1, &message_p); - - switch (ITTI_MSG_ID(message_p)) { - case INITIALIZE_MESSAGE: - /* Start eNB thread */ - LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p)); - start_eNB = 1; - break; - - case TERMINATE_MESSAGE: - printf("received terminate message\n"); - oai_exit=1; - itti_exit_task (); - break; - - default: - LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); - break; - } - } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE); + } - result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } + do { + // Wait for a message + itti_receive_msg (TASK_L2L1, &message_p); - do { - // Wait for a message - itti_receive_msg (TASK_L2L1, &message_p); + switch (ITTI_MSG_ID(message_p)) { + case TERMINATE_MESSAGE: + oai_exit=1; + itti_exit_task (); + break; - switch (ITTI_MSG_ID(message_p)) { - case TERMINATE_MESSAGE: - oai_exit=1; - itti_exit_task (); - break; + case ACTIVATE_MESSAGE: + start_UE = 1; + break; - case ACTIVATE_MESSAGE: - start_UE = 1; - break; + case DEACTIVATE_MESSAGE: + start_UE = 0; + break; - case DEACTIVATE_MESSAGE: - start_UE = 0; - break; + case MESSAGE_TEST: + LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); + break; - case MESSAGE_TEST: - LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); - break; - - default: - LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); - break; - } + default: + LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); + break; + } - result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } while(!oai_exit); + result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } while(!oai_exit); - return NULL; + return NULL; } #endif - -static void get_options (int argc, char **argv) -{ - int c; - // char line[1000]; - // int l; - int k,i;//,j,k; + +static void get_options (int argc, char **argv) { + int c; + // char line[1000]; + // int l; + int k,i;//,j,k; #if defined(OAI_USRP) || defined(CPRIGW) - int clock_src; + int clock_src; #endif - int CC_id; - + int CC_id; const Enb_properties_array_t *enb_properties; - enum long_option_e { - LONG_OPTION_START = 0x100, /* Start after regular single char options */ - LONG_OPTION_RF_CONFIG_FILE, - LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS, - LONG_OPTION_CALIB_UE_RX, - LONG_OPTION_CALIB_UE_RX_MED, - LONG_OPTION_CALIB_UE_RX_BYP, - LONG_OPTION_DEBUG_UE_PRACH, - LONG_OPTION_NO_L2_CONNECT, - LONG_OPTION_CALIB_PRACH_TX, - LONG_OPTION_RXGAIN, - LONG_OPTION_RXGAINOFF, - LONG_OPTION_TXGAIN, - LONG_OPTION_SCANCARRIER, - LONG_OPTION_MAXPOWER, - LONG_OPTION_DUMP_FRAME, - LONG_OPTION_LOOPMEMORY, - LONG_OPTION_PHYTEST, - LONG_OPTION_USIMTEST, - LONG_OPTION_MMAPPED_DMA, - LONG_OPTION_EXTERNAL_CLOCK, - LONG_OPTION_WAIT_FOR_SYNC, - LONG_OPTION_SINGLE_THREAD_DISABLE, + enum long_option_e { + LONG_OPTION_START = 0x100, /* Start after regular single char options */ + LONG_OPTION_RF_CONFIG_FILE, + LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS, + LONG_OPTION_CALIB_UE_RX, + LONG_OPTION_CALIB_UE_RX_MED, + LONG_OPTION_CALIB_UE_RX_BYP, + LONG_OPTION_DEBUG_UE_PRACH, + LONG_OPTION_NO_L2_CONNECT, + LONG_OPTION_CALIB_PRACH_TX, + LONG_OPTION_RXGAIN, + LONG_OPTION_RXGAINOFF, + LONG_OPTION_TXGAIN, + LONG_OPTION_NBRXANT, + LONG_OPTION_NBTXANT, + LONG_OPTION_SCANCARRIER, + LONG_OPTION_MAXPOWER, + LONG_OPTION_DUMP_FRAME, + LONG_OPTION_LOOPMEMORY, + LONG_OPTION_PHYTEST, + LONG_OPTION_USIMTEST, + LONG_OPTION_MMAPPED_DMA, + LONG_OPTION_EXTERNAL_CLOCK, + LONG_OPTION_WAIT_FOR_SYNC, + LONG_OPTION_SINGLE_THREAD_DISABLE, + LONG_OPTION_THREADIQ, + LONG_OPTION_THREADODDSUBFRAME, + LONG_OPTION_THREADEVENSUBFRAME, + LONG_OPTION_DEMOD_SHIFT, #if T_TRACER - LONG_OPTION_T_PORT, - LONG_OPTION_T_NOWAIT, - LONG_OPTION_T_DONT_FORK, + LONG_OPTION_T_PORT, + LONG_OPTION_T_NOWAIT, + LONG_OPTION_T_DONT_FORK, #endif - }; - static const struct option long_options[] = { - {"rf-config-file",required_argument, NULL, LONG_OPTION_RF_CONFIG_FILE}, - {"ulsch-max-errors",required_argument, NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS}, - {"calib-ue-rx", required_argument, NULL, LONG_OPTION_CALIB_UE_RX}, - {"calib-ue-rx-med", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_MED}, - {"calib-ue-rx-byp", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_BYP}, - {"debug-ue-prach", no_argument, NULL, LONG_OPTION_DEBUG_UE_PRACH}, - {"no-L2-connect", no_argument, NULL, LONG_OPTION_NO_L2_CONNECT}, - {"calib-prach-tx", no_argument, NULL, LONG_OPTION_CALIB_PRACH_TX}, - {"ue-rxgain", required_argument, NULL, LONG_OPTION_RXGAIN}, - {"ue-rxgain-off", required_argument, NULL, LONG_OPTION_RXGAINOFF}, - {"ue-txgain", required_argument, NULL, LONG_OPTION_TXGAIN}, - {"ue-scan-carrier", no_argument, NULL, LONG_OPTION_SCANCARRIER}, - {"ue-max-power", required_argument, NULL, LONG_OPTION_MAXPOWER}, - {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME}, - {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, - {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, - {"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST}, - {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, - {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK}, - {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC}, - {"single-thread-disable", no_argument, NULL, LONG_OPTION_SINGLE_THREAD_DISABLE}, + }; + + static const struct option long_options[] = { + {"rf-config-file",required_argument, NULL, LONG_OPTION_RF_CONFIG_FILE}, + {"ulsch-max-errors",required_argument, NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS}, + {"calib-ue-rx", required_argument, NULL, LONG_OPTION_CALIB_UE_RX}, + {"calib-ue-rx-med", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_MED}, + {"calib-ue-rx-byp", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_BYP}, + {"debug-ue-prach", no_argument, NULL, LONG_OPTION_DEBUG_UE_PRACH}, + {"no-L2-connect", no_argument, NULL, LONG_OPTION_NO_L2_CONNECT}, + {"calib-prach-tx", no_argument, NULL, LONG_OPTION_CALIB_PRACH_TX}, + {"ue-rxgain", required_argument, NULL, LONG_OPTION_RXGAIN}, + {"ue-rxgain-off", required_argument, NULL, LONG_OPTION_RXGAINOFF}, + {"ue-txgain", required_argument, NULL, LONG_OPTION_TXGAIN}, + {"ue-nb-ant-rx", required_argument, NULL, LONG_OPTION_NBRXANT}, + {"ue-nb-ant-tx", required_argument, NULL, LONG_OPTION_NBTXANT}, + {"ue-scan-carrier", no_argument, NULL, LONG_OPTION_SCANCARRIER}, + {"ue-max-power", required_argument, NULL, LONG_OPTION_MAXPOWER}, + {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME}, + {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, + {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, + {"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST}, + {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, + {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK}, + {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC}, + {"single-thread-disable", no_argument, NULL, LONG_OPTION_SINGLE_THREAD_DISABLE}, + {"threadIQ", required_argument, NULL, LONG_OPTION_THREADIQ}, + {"threadOddSubframe", required_argument, NULL, LONG_OPTION_THREADODDSUBFRAME}, + {"threadEvenSubframe", required_argument, NULL, LONG_OPTION_THREADEVENSUBFRAME}, + {"dlsch-demod-shift", required_argument, NULL, LONG_OPTION_DEMOD_SHIFT}, #if T_TRACER - {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, - {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, - {"T_dont_fork", no_argument, 0, LONG_OPTION_T_DONT_FORK}, + {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, + {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, + {"T_dont_fork", no_argument, 0, LONG_OPTION_T_DONT_FORK}, #endif {NULL, 0, NULL, 0} }; @@ -802,7 +753,12 @@ static void get_options (int argc, char **argv) tx_gain[0][i] = atof(optarg); break; - + case LONG_OPTION_NBRXANT: + nb_antenna_rx = atof(optarg); + break; + case LONG_OPTION_NBTXANT: + nb_antenna_tx = atof(optarg); + break; case LONG_OPTION_SCANCARRIER: UE_scan_carrier=1; @@ -841,393 +797,408 @@ static void get_options (int argc, char **argv) wait_for_sync = 1; break; -#if T_TRACER - case LONG_OPTION_T_PORT: { - extern int T_port; - if (optarg == NULL) abort(); /* should not happen */ - T_port = atoi(optarg); - break; + case LONG_OPTION_THREADIQ: + threads.iq=atoi(optarg); + break; + case LONG_OPTION_THREADODDSUBFRAME: + threads.odd=atoi(optarg); + break; + case LONG_OPTION_THREADEVENSUBFRAME: + threads.even=atoi(optarg); + break; + case LONG_OPTION_DEMOD_SHIFT: { + extern int16_t dlsch_demod_shift; + dlsch_demod_shift = atof(optarg); + break; } +#if T_TRACER + case LONG_OPTION_T_PORT: { + extern int T_port; + if (optarg == NULL) abort(); /* should not happen */ + T_port = atoi(optarg); + break; + } - case LONG_OPTION_T_NOWAIT: { - extern int T_wait; - T_wait = 0; - break; - } + case LONG_OPTION_T_NOWAIT: { + extern int T_wait; + T_wait = 0; + break; + } - case LONG_OPTION_T_DONT_FORK: { - extern int T_dont_fork; - T_dont_fork = 1; - break; - } + case LONG_OPTION_T_DONT_FORK: { + extern int T_dont_fork; + T_dont_fork = 1; + break; + } #endif - case 'A': - timing_advance = atoi (optarg); - break; + case 'A': + timing_advance = atoi (optarg); + break; - case 'C': - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - downlink_frequency[CC_id][0] = atof(optarg); // Use float to avoid issue with frequency over 2^31. - downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; - downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; - downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; - printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); - } + case 'C': + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + downlink_frequency[CC_id][0] = atof(optarg); // Use float to avoid issue with frequency over 2^31. + downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; + downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; + downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; + printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); + } - UE_scan=0; + UE_scan=0; - break; + break; - case 'a': - chain_offset = atoi(optarg); - break; + case 'a': + chain_offset = atoi(optarg); + break; - case 'd': + case 'd': #ifdef XFORMS - do_forms=1; - printf("Running with XFORMS!\n"); + do_forms=1; + printf("Running with XFORMS!\n"); #endif - break; - - case 'E': - threequarter_fs=1; - break; + break; + + case 'E': + threequarter_fs=1; + break; - case 'K': + case 'K': #if defined(ENABLE_ITTI) - itti_dump_file = strdup(optarg); + itti_dump_file = strdup(optarg); #else - printf("-K option is disabled when ENABLE_ITTI is not defined\n"); + printf("-K option is disabled when ENABLE_ITTI is not defined\n"); #endif - break; - - case 'O': - conf_config_file_name = optarg; - break; - - case 'U': - UE_flag = 1; - break; - - case 'm': - target_dl_mcs = atoi (optarg); - break; - - case 't': - target_ul_mcs = atoi (optarg); - break; - - case 'W': - opt_enabled=1; - opt_type = OPT_WIRESHARK; - strncpy(in_ip, "127.0.0.1", sizeof(in_ip)); - in_ip[sizeof(in_ip) - 1] = 0; // terminate string - printf("Enabling OPT for wireshark for local interface"); - /* - if (optarg == NULL){ - in_ip[0] =NULL; - printf("Enabling OPT for wireshark for local interface"); - } else { - strncpy(in_ip, optarg, sizeof(in_ip)); - in_ip[sizeof(in_ip) - 1] = 0; // terminate string - printf("Enabling OPT for wireshark with %s \n",in_ip); - } - */ - break; - - case 'P': - opt_type = OPT_PCAP; - opt_enabled=1; - - if (optarg == NULL) { - strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path)); - in_path[sizeof(in_path) - 1] = 0; // terminate string - printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap"); - } else { - strncpy(in_path, optarg, sizeof(in_path)); - in_path[sizeof(in_path) - 1] = 0; // terminate string - printf("Enabling OPT for PCAP with the following file %s \n",in_path); - } - - break; - - case 'V': - ouput_vcd = 1; - break; - - case 'q': - opp_enabled = 1; - break; - - case 'R' : - online_log_messages =1; - break; - - case 'r': - UE_scan = 0; - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - switch(atoi(optarg)) { - case 6: - frame_parms[CC_id]->N_RB_DL=6; - frame_parms[CC_id]->N_RB_UL=6; - break; - - case 25: - frame_parms[CC_id]->N_RB_DL=25; - frame_parms[CC_id]->N_RB_UL=25; - break; - - case 50: - frame_parms[CC_id]->N_RB_DL=50; - frame_parms[CC_id]->N_RB_UL=50; - break; - - case 100: - frame_parms[CC_id]->N_RB_DL=100; - frame_parms[CC_id]->N_RB_UL=100; - break; - - default: - printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg)); - break; - } - } - - break; - - case 's': + break; + + case 'O': + conf_config_file_name = optarg; + break; + + case 'U': + UE_flag = 1; + break; + + case 'm': + target_dl_mcs = atoi (optarg); + break; + + case 't': + target_ul_mcs = atoi (optarg); + break; + + case 'W': + opt_enabled=1; + opt_type = OPT_WIRESHARK; + strncpy(in_ip, "127.0.0.1", sizeof(in_ip)); + in_ip[sizeof(in_ip) - 1] = 0; // terminate string + printf("Enabling OPT for wireshark for local interface"); + /* + if (optarg == NULL){ + in_ip[0] =NULL; + printf("Enabling OPT for wireshark for local interface"); + } else { + strncpy(in_ip, optarg, sizeof(in_ip)); + in_ip[sizeof(in_ip) - 1] = 0; // terminate string + printf("Enabling OPT for wireshark with %s \n",in_ip); + } + */ + break; + + case 'P': + opt_type = OPT_PCAP; + opt_enabled=1; + + if (optarg == NULL) { + strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path)); + in_path[sizeof(in_path) - 1] = 0; // terminate string + printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap"); + } else { + strncpy(in_path, optarg, sizeof(in_path)); + in_path[sizeof(in_path) - 1] = 0; // terminate string + printf("Enabling OPT for PCAP with the following file %s \n",in_path); + } + + break; + + case 'V': + ouput_vcd = 1; + break; + + case 'q': + opp_enabled = 1; + break; + + case 'R' : + online_log_messages =1; + break; + + case 'r': + UE_scan = 0; + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + switch(atoi(optarg)) { + case 6: + frame_parms[CC_id]->N_RB_DL=6; + frame_parms[CC_id]->N_RB_UL=6; + break; + + case 25: + frame_parms[CC_id]->N_RB_DL=25; + frame_parms[CC_id]->N_RB_UL=25; + break; + + case 50: + frame_parms[CC_id]->N_RB_DL=50; + frame_parms[CC_id]->N_RB_UL=50; + break; + + case 100: + frame_parms[CC_id]->N_RB_DL=100; + frame_parms[CC_id]->N_RB_UL=100; + break; + + default: + printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg)); + break; + } + } + + break; + + case 's': #if defined(OAI_USRP) || defined(CPRIGW) - clock_src = atoi(optarg); + clock_src = atoi(optarg); - if (clock_src == 0) { - // char ref[128] = "internal"; - //strncpy(uhd_ref, ref, strlen(ref)+1); - } else if (clock_src == 1) { - //char ref[128] = "external"; - //strncpy(uhd_ref, ref, strlen(ref)+1); - } + if (clock_src == 0) { + // char ref[128] = "internal"; + //strncpy(uhd_ref, ref, strlen(ref)+1); + } else if (clock_src == 1) { + //char ref[128] = "external"; + //strncpy(uhd_ref, ref, strlen(ref)+1); + } #else - printf("Note: -s not defined for ExpressMIMO2\n"); + printf("Note: -s not defined for ExpressMIMO2\n"); #endif - break; + break; + + case 'S': + exit_missed_slots=0; + printf("Skip exit for missed slots\n"); + break; + + case 'g': + glog_level=atoi(optarg); // value between 1 - 9 + break; + + case 'F': + break; + + case 'G': + glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75 + break; + + case 'x': + printf("Transmission mode should be set in config file now\n"); + exit(-1); + /* + transmission_mode = atoi(optarg); + + if (transmission_mode > 7) { + printf("Transmission mode %d not supported for the moment\n",transmission_mode); + exit(-1); + } + */ + break; + + case 'T': + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) + frame_parms[CC_id]->frame_type = TDD; + break; + + case 'h': + help (); + exit (-1); - case 'S': - exit_missed_slots=0; - printf("Skip exit for missed slots\n"); - break; - - case 'g': - glog_level=atoi(optarg); // value between 1 - 9 - break; - - case 'F': - break; - - case 'G': - glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75 - break; - - case 'x': - printf("Transmission mode should be set in config file now\n"); - exit(-1); - /* - transmission_mode = atoi(optarg); - - if (transmission_mode > 7) { - printf("Transmission mode %d not supported for the moment\n",transmission_mode); - exit(-1); - } - */ - break; - - case 'T': - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) - frame_parms[CC_id]->frame_type = TDD; - break; - - case 'h': - help (); - exit (-1); - - default: - help (); - exit (-1); - break; - } - } - - if (UE_flag == 0) - AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n"); - - if ((UE_flag == 0) && (conf_config_file_name != NULL)) { - int i,j; - - NB_eNB_INST = 1; - - /* Read eNB configuration file */ - enb_properties = enb_config_init(conf_config_file_name); - - AssertFatal (NB_eNB_INST <= enb_properties->number, - "Number of eNB is greater than eNB defined in configuration file %s (%d/%d)!", - conf_config_file_name, NB_eNB_INST, enb_properties->number); - - /* Update some simulation parameters */ - for (i=0; i < enb_properties->number; i++) { - AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc, - "lte-softmodem compiled with MAX_NUM_CCs=%d, but only %d CCs configured for eNB %d!", - MAX_NUM_CCs, enb_properties->properties[i]->nb_cc, i); - eth_params = (eth_params_t*)malloc(enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); - memset(eth_params, 0, enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); - - for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) { - - if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) { - local_remote_radio = BBU_REMOTE_RADIO_HEAD; - (eth_params+j)->local_if_name = enb_properties->properties[i]->rrh_gw_config[j].rrh_gw_if_name; - (eth_params+j)->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; - (eth_params+j)->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; - (eth_params+j)->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; - (eth_params+j)->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; - - if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) { - (eth_params+j)->transp_preference = ETH_RAW_MODE; - } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4p5 == 1) { - (eth_params+j)->transp_preference = ETH_RAW_IF4p5_MODE; - } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4p5 == 1) { - (eth_params+j)->transp_preference = ETH_UDP_IF4p5_MODE; - } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) { - (eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS; - } else { - (eth_params+j)->transp_preference = ETH_UDP_MODE; - } - - (eth_params+j)->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; - (eth_params+j)->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; - (eth_params+j)->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; - if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) { - (eth_params+j)->rf_preference = EXMIMO_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) { - (eth_params+j)->rf_preference = USRP_B200_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) { - (eth_params+j)->rf_preference = USRP_X300_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) { - (eth_params+j)->rf_preference = BLADERF_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) { - //(eth_params+j)->rf_preference = LMSSDR_DEV; - } else { - (eth_params+j)->rf_preference = 0; - } - } else { - local_remote_radio = BBU_LOCAL_RADIO_HEAD; + default: + help (); + exit (-1); + break; } - - } - - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - - - node_function[CC_id] = enb_properties->properties[i]->cc_node_function[CC_id]; - node_timing[CC_id] = enb_properties->properties[i]->cc_node_timing[CC_id]; - node_synch_ref[CC_id] = enb_properties->properties[i]->cc_node_synch_ref[CC_id]; - - frame_parms[CC_id]->frame_type = enb_properties->properties[i]->frame_type[CC_id]; - frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id]; - frame_parms[CC_id]->tdd_config_S = enb_properties->properties[i]->tdd_config_s[CC_id]; - frame_parms[CC_id]->Ncp = enb_properties->properties[i]->prefix_type[CC_id]; - - //for (j=0; j < enb_properties->properties[i]->nb_cc; j++ ){ - frame_parms[CC_id]->Nid_cell = enb_properties->properties[i]->Nid_cell[CC_id]; - frame_parms[CC_id]->N_RB_DL = enb_properties->properties[i]->N_RB_DL[CC_id]; - frame_parms[CC_id]->N_RB_UL = enb_properties->properties[i]->N_RB_DL[CC_id]; - frame_parms[CC_id]->nb_antennas_tx = enb_properties->properties[i]->nb_antennas_tx[CC_id]; - frame_parms[CC_id]->nb_antenna_ports_eNB = enb_properties->properties[i]->nb_antenna_ports[CC_id]; - frame_parms[CC_id]->nb_antennas_rx = enb_properties->properties[i]->nb_antennas_rx[CC_id]; - - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[i]->prach_config_index[CC_id]; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset = enb_properties->properties[i]->prach_freq_offset[CC_id]; - - frame_parms[CC_id]->mode1_flag = (frame_parms[CC_id]->nb_antenna_ports_eNB == 1) ? 1 : 0; - frame_parms[CC_id]->threequarter_fs = threequarter_fs; - - //} // j - } - - - init_all_otg(0); - g_otg->seed = 0; - init_seeds(g_otg->seed); - - for (k=0; k<enb_properties->properties[i]->num_otg_elements; k++) { - j=enb_properties->properties[i]->otg_ue_id[k]; // ue_id - g_otg->application_idx[i][j] = 1; - //g_otg->packet_gen_type=SUBSTRACT_STRING; - g_otg->background[i][j][0] =enb_properties->properties[i]->otg_bg_traffic[k]; - g_otg->application_type[i][j][0] =enb_properties->properties[i]->otg_app_type[k];// BCBR; //MCBR, BCBR - - printf("[OTG] configuring traffic type %d for eNB %d UE %d (Background traffic is %s)\n", - g_otg->application_type[i][j][0], i, j,(g_otg->background[i][j][0]==1)?"Enabled":"Disabled"); - } + } - init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1); - - - glog_level = enb_properties->properties[i]->glog_level; - glog_verbosity = enb_properties->properties[i]->glog_verbosity; - hw_log_level = enb_properties->properties[i]->hw_log_level; - hw_log_verbosity = enb_properties->properties[i]->hw_log_verbosity ; - phy_log_level = enb_properties->properties[i]->phy_log_level; - phy_log_verbosity = enb_properties->properties[i]->phy_log_verbosity; - mac_log_level = enb_properties->properties[i]->mac_log_level; - mac_log_verbosity = enb_properties->properties[i]->mac_log_verbosity; - rlc_log_level = enb_properties->properties[i]->rlc_log_level; - rlc_log_verbosity = enb_properties->properties[i]->rlc_log_verbosity; - pdcp_log_level = enb_properties->properties[i]->pdcp_log_level; - pdcp_log_verbosity = enb_properties->properties[i]->pdcp_log_verbosity; - rrc_log_level = enb_properties->properties[i]->rrc_log_level; - rrc_log_verbosity = enb_properties->properties[i]->rrc_log_verbosity; + if (UE_flag == 0) + AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n"); + + if ((UE_flag == 0) && (conf_config_file_name != NULL)) { + int i,j; + + NB_eNB_INST = 1; + + /* Read eNB configuration file */ + enb_properties = enb_config_init(conf_config_file_name); + + AssertFatal (NB_eNB_INST <= enb_properties->number, + "Number of eNB is greater than eNB defined in configuration file %s (%d/%d)!", + conf_config_file_name, NB_eNB_INST, enb_properties->number); + + /* Update some simulation parameters */ + for (i=0; i < enb_properties->number; i++) { + AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc, + "lte-softmodem compiled with MAX_NUM_CCs=%d, but only %d CCs configured for eNB %d!", + MAX_NUM_CCs, enb_properties->properties[i]->nb_cc, i); + eth_params = (eth_params_t*)malloc(enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); + memset(eth_params, 0, enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); + + for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) { + + if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) { + local_remote_radio = BBU_REMOTE_RADIO_HEAD; + (eth_params+j)->local_if_name = enb_properties->properties[i]->rrh_gw_config[j].rrh_gw_if_name; + (eth_params+j)->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; + (eth_params+j)->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; + (eth_params+j)->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; + (eth_params+j)->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; + + if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) { + (eth_params+j)->transp_preference = ETH_RAW_MODE; + } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4p5 == 1) { + (eth_params+j)->transp_preference = ETH_RAW_IF4p5_MODE; + } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4p5 == 1) { + (eth_params+j)->transp_preference = ETH_UDP_IF4p5_MODE; + } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) { + (eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS; + } else { + (eth_params+j)->transp_preference = ETH_UDP_MODE; + } + + (eth_params+j)->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; + (eth_params+j)->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; + (eth_params+j)->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; + if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) { + (eth_params+j)->rf_preference = EXMIMO_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) { + (eth_params+j)->rf_preference = USRP_B200_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) { + (eth_params+j)->rf_preference = USRP_X300_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) { + (eth_params+j)->rf_preference = BLADERF_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) { + //(eth_params+j)->rf_preference = LMSSDR_DEV; + } else { + (eth_params+j)->rf_preference = 0; + } + (eth_params+j)->if_compress = enb_properties->properties[i]->rrh_gw_config[j].if_compress; + } else { + local_remote_radio = BBU_LOCAL_RADIO_HEAD; + } + + } + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + + + node_function[CC_id] = enb_properties->properties[i]->cc_node_function[CC_id]; + node_timing[CC_id] = enb_properties->properties[i]->cc_node_timing[CC_id]; + node_synch_ref[CC_id] = enb_properties->properties[i]->cc_node_synch_ref[CC_id]; + + frame_parms[CC_id]->frame_type = enb_properties->properties[i]->frame_type[CC_id]; + frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id]; + frame_parms[CC_id]->tdd_config_S = enb_properties->properties[i]->tdd_config_s[CC_id]; + frame_parms[CC_id]->Ncp = enb_properties->properties[i]->prefix_type[CC_id]; + + //for (j=0; j < enb_properties->properties[i]->nb_cc; j++ ){ + frame_parms[CC_id]->Nid_cell = enb_properties->properties[i]->Nid_cell[CC_id]; + frame_parms[CC_id]->N_RB_DL = enb_properties->properties[i]->N_RB_DL[CC_id]; + frame_parms[CC_id]->N_RB_UL = enb_properties->properties[i]->N_RB_DL[CC_id]; + frame_parms[CC_id]->nb_antennas_tx = enb_properties->properties[i]->nb_antennas_tx[CC_id]; + frame_parms[CC_id]->nb_antenna_ports_eNB = enb_properties->properties[i]->nb_antenna_ports[CC_id]; + frame_parms[CC_id]->nb_antennas_rx = enb_properties->properties[i]->nb_antennas_rx[CC_id]; + + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[i]->prach_config_index[CC_id]; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset = enb_properties->properties[i]->prach_freq_offset[CC_id]; + + frame_parms[CC_id]->mode1_flag = (frame_parms[CC_id]->nb_antenna_ports_eNB == 1) ? 1 : 0; + frame_parms[CC_id]->threequarter_fs = threequarter_fs; + + //} // j + } + + + init_all_otg(0); + g_otg->seed = 0; + init_seeds(g_otg->seed); + + for (k=0; k<enb_properties->properties[i]->num_otg_elements; k++) { + j=enb_properties->properties[i]->otg_ue_id[k]; // ue_id + g_otg->application_idx[i][j] = 1; + //g_otg->packet_gen_type=SUBSTRACT_STRING; + g_otg->background[i][j][0] =enb_properties->properties[i]->otg_bg_traffic[k]; + g_otg->application_type[i][j][0] =enb_properties->properties[i]->otg_app_type[k];// BCBR; //MCBR, BCBR + + printf("[OTG] configuring traffic type %d for eNB %d UE %d (Background traffic is %s)\n", + g_otg->application_type[i][j][0], i, j,(g_otg->background[i][j][0]==1)?"Enabled":"Disabled"); + } + + init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1); + + + glog_level = enb_properties->properties[i]->glog_level; + glog_verbosity = enb_properties->properties[i]->glog_verbosity; + hw_log_level = enb_properties->properties[i]->hw_log_level; + hw_log_verbosity = enb_properties->properties[i]->hw_log_verbosity ; + phy_log_level = enb_properties->properties[i]->phy_log_level; + phy_log_verbosity = enb_properties->properties[i]->phy_log_verbosity; + mac_log_level = enb_properties->properties[i]->mac_log_level; + mac_log_verbosity = enb_properties->properties[i]->mac_log_verbosity; + rlc_log_level = enb_properties->properties[i]->rlc_log_level; + rlc_log_verbosity = enb_properties->properties[i]->rlc_log_verbosity; + pdcp_log_level = enb_properties->properties[i]->pdcp_log_level; + pdcp_log_verbosity = enb_properties->properties[i]->pdcp_log_verbosity; + rrc_log_level = enb_properties->properties[i]->rrc_log_level; + rrc_log_verbosity = enb_properties->properties[i]->rrc_log_verbosity; # if defined(ENABLE_USE_MME) - gtpu_log_level = enb_properties->properties[i]->gtpu_log_level; - gtpu_log_verbosity = enb_properties->properties[i]->gtpu_log_verbosity; - udp_log_level = enb_properties->properties[i]->udp_log_level; - udp_log_verbosity = enb_properties->properties[i]->udp_log_verbosity; + gtpu_log_level = enb_properties->properties[i]->gtpu_log_level; + gtpu_log_verbosity = enb_properties->properties[i]->gtpu_log_verbosity; + udp_log_level = enb_properties->properties[i]->udp_log_level; + udp_log_verbosity = enb_properties->properties[i]->udp_log_verbosity; #endif #if defined (ENABLE_SECURITY) - osa_log_level = enb_properties->properties[i]->osa_log_level; - osa_log_verbosity = enb_properties->properties[i]->osa_log_verbosity; + osa_log_level = enb_properties->properties[i]->osa_log_level; + osa_log_verbosity = enb_properties->properties[i]->osa_log_verbosity; #endif - // adjust the log - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - for (k = 0 ; k < 4; k++) { - downlink_frequency[CC_id][k] = enb_properties->properties[i]->downlink_frequency[CC_id]; - uplink_frequency_offset[CC_id][k] = enb_properties->properties[i]->uplink_frequency_offset[CC_id]; - rx_gain[CC_id][k] = (double)enb_properties->properties[i]->rx_gain[CC_id]; - tx_gain[CC_id][k] = (double)enb_properties->properties[i]->tx_gain[CC_id]; - } + // adjust the log + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + for (k = 0 ; k < 4; k++) { + downlink_frequency[CC_id][k] = enb_properties->properties[i]->downlink_frequency[CC_id]; + uplink_frequency_offset[CC_id][k] = enb_properties->properties[i]->uplink_frequency_offset[CC_id]; + rx_gain[CC_id][k] = (double)enb_properties->properties[i]->rx_gain[CC_id]; + tx_gain[CC_id][k] = (double)enb_properties->properties[i]->tx_gain[CC_id]; + } - printf("Downlink frequency/ uplink offset of CC_id %d set to %ju/%d\n", CC_id, - enb_properties->properties[i]->downlink_frequency[CC_id], - enb_properties->properties[i]->uplink_frequency_offset[CC_id]); + printf("Downlink frequency/ uplink offset of CC_id %d set to %ju/%d\n", CC_id, + enb_properties->properties[i]->downlink_frequency[CC_id], + enb_properties->properties[i]->uplink_frequency_offset[CC_id]); - } // CC_id - }// i + } // CC_id + }// i - //this is needed for phy-test option - transmission_mode = enb_properties->properties[0]->ue_TransmissionMode[0]+1; + //this is needed for phy-test option + transmission_mode = enb_properties->properties[0]->ue_TransmissionMode[0]+1; - } else if (UE_flag == 1) { - if (conf_config_file_name != NULL) { - - // Here the configuration file is the XER encoded UE capabilities - // Read it in and store in asn1c data structures - strcpy(uecap_xer,conf_config_file_name); - uecap_xer_in=1; + } else if (UE_flag == 1) { + if (conf_config_file_name != NULL) { + + // Here the configuration file is the XER encoded UE capabilities + // Read it in and store in asn1c data structures + strcpy(uecap_xer,conf_config_file_name); + uecap_xer_in=1; + } } - } } #if T_TRACER @@ -1239,47 +1210,47 @@ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { - int CC_id; + int CC_id; - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS)); - /* Set some default values that may be overwritten while reading options */ - frame_parms[CC_id]->frame_type = FDD; - frame_parms[CC_id]->tdd_config = 3; - frame_parms[CC_id]->tdd_config_S = 0; - frame_parms[CC_id]->N_RB_DL = 100; - frame_parms[CC_id]->N_RB_UL = 100; - frame_parms[CC_id]->Ncp = NORMAL; - frame_parms[CC_id]->Ncp_UL = NORMAL; - frame_parms[CC_id]->Nid_cell = 0; - frame_parms[CC_id]->num_MBSFN_config = 0; - frame_parms[CC_id]->nb_antenna_ports_eNB = 1; - frame_parms[CC_id]->nb_antennas_tx = 1; - frame_parms[CC_id]->nb_antennas_rx = 1; - - frame_parms[CC_id]->nushift = 0; - - frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; - frame_parms[CC_id]->phich_config_common.phich_duration = normal; - // UL RS Config - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; - - frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; - - downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31. - downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; - downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; - downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; - //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS)); + /* Set some default values that may be overwritten while reading options */ + frame_parms[CC_id]->frame_type = FDD; + frame_parms[CC_id]->tdd_config = 3; + frame_parms[CC_id]->tdd_config_S = 0; + frame_parms[CC_id]->N_RB_DL = 100; + frame_parms[CC_id]->N_RB_UL = 100; + frame_parms[CC_id]->Ncp = NORMAL; + frame_parms[CC_id]->Ncp_UL = NORMAL; + frame_parms[CC_id]->Nid_cell = 0; + frame_parms[CC_id]->num_MBSFN_config = 0; + frame_parms[CC_id]->nb_antenna_ports_eNB = 1; + frame_parms[CC_id]->nb_antennas_tx = 1; + frame_parms[CC_id]->nb_antennas_rx = 1; + + frame_parms[CC_id]->nushift = 0; + + frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; + frame_parms[CC_id]->phich_config_common.phich_duration = normal; + // UL RS Config + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + + frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + + downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31. + downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; + downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; + downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; + //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); - } + } } @@ -1287,43 +1258,45 @@ void init_openair0(void); void init_openair0() { - int card; - int i; + int card; + int i; + + for (card=0; card<MAX_CARDS; card++) { + + openair0_cfg[card].mmapped_dma=mmapped_dma; + openair0_cfg[card].configFilename = NULL; + + if(frame_parms[0]->N_RB_DL == 100) { + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=23.04e6; + openair0_cfg[card].samples_per_frame = 230400; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } else { + openair0_cfg[card].sample_rate=30.72e6; + openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } + } else if(frame_parms[0]->N_RB_DL == 50) { + openair0_cfg[card].sample_rate=15.36e6; + openair0_cfg[card].samples_per_frame = 153600; + openair0_cfg[card].tx_bw = 5e6; + openair0_cfg[card].rx_bw = 5e6; + } else if (frame_parms[0]->N_RB_DL == 25) { + openair0_cfg[card].sample_rate=7.68e6; + openair0_cfg[card].samples_per_frame = 76800; + openair0_cfg[card].tx_bw = 2.5e6; + openair0_cfg[card].rx_bw = 2.5e6; + } else if (frame_parms[0]->N_RB_DL == 6) { + openair0_cfg[card].sample_rate=1.92e6; + openair0_cfg[card].samples_per_frame = 19200; + openair0_cfg[card].tx_bw = 1.5e6; + openair0_cfg[card].rx_bw = 1.5e6; + } - for (card=0; card<MAX_CARDS; card++) { - openair0_cfg[card].mmapped_dma=mmapped_dma; - openair0_cfg[card].configFilename = NULL; - if(frame_parms[0]->N_RB_DL == 100) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - } else if(frame_parms[0]->N_RB_DL == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - openair0_cfg[card].tx_bw = 5e6; - openair0_cfg[card].rx_bw = 5e6; - } else if (frame_parms[0]->N_RB_DL == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - openair0_cfg[card].tx_bw = 2.5e6; - openair0_cfg[card].rx_bw = 2.5e6; - } else if (frame_parms[0]->N_RB_DL == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - openair0_cfg[card].tx_bw = 1.5e6; - openair0_cfg[card].rx_bw = 1.5e6; - } if (frame_parms[0]->frame_type==TDD) openair0_cfg[card].duplex_mode = duplex_mode_TDD; @@ -1353,7 +1326,7 @@ void init_openair0() { openair0_cfg[card].clock_source = clock_source; - openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx)); + openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); for (i=0; i<4; i++) { @@ -1387,170 +1360,180 @@ void init_openair0() { } } -int main( int argc, char **argv ) -{ - int i,j,k,aa,re; +int main( int argc, char **argv ) { + int i,j,k,aa,re; #if defined (XFORMS) - void *status; + void *status; #endif - int CC_id; - uint8_t abstraction_flag=0; - uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; + int CC_id; + uint8_t abstraction_flag=0; + uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; #if defined (XFORMS) - int ret; + int ret; #endif + start_background_system(); + #ifdef DEBUG_CONSOLE - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); #endif - PHY_VARS_UE *UE[MAX_NUM_CCs]; + PHY_VARS_UE *UE[MAX_NUM_CCs]; + + mode = normal_txrx; + memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS); - mode = normal_txrx; - memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS); + memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); - memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); - set_latency_target(); + set_latency_target(); - // set default parameters - set_default_frame_parms(frame_parms); + // set default parameters + set_default_frame_parms(frame_parms); + + // initialize logging + logInit(); + + // get options and fill parameters from configuration file + get_options (argc, argv); //Command-line options, enb_properties - // initialize logging - logInit(); - // get options and fill parameters from configuration file - get_options (argc, argv); //Command-line options, enb_properties - - #if T_TRACER - T_init(T_port, T_wait, T_dont_fork); + T_init(T_port, T_wait, T_dont_fork); #endif - // initialize the log (see log.h for details) - set_glog(glog_level, glog_verbosity); - - //randominit (0); - set_taus_seed (0); + // initialize the log (see log.h for details) + set_glog(glog_level, glog_verbosity); - if (UE_flag==1) { - printf("configuring for UE\n"); + //randominit (0); + set_taus_seed (0); - set_comp_log(HW, LOG_DEBUG, LOG_HIGH, 1); - set_comp_log(PHY, LOG_DEBUG, LOG_HIGH, 1); - set_comp_log(MAC, LOG_INFO, LOG_HIGH, 1); - set_comp_log(RLC, LOG_INFO, LOG_HIGH, 1); - set_comp_log(PDCP, LOG_INFO, LOG_HIGH, 1); - set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1); - set_comp_log(RRC, LOG_INFO, LOG_HIGH, 1); + if (UE_flag==1) { + printf("configuring for UE\n"); + + set_comp_log(HW, LOG_DEBUG, LOG_HIGH, 1); + set_comp_log(PHY, LOG_DEBUG, LOG_HIGH, 1); + set_comp_log(MAC, LOG_INFO, LOG_HIGH, 1); + set_comp_log(RLC, LOG_INFO, LOG_HIGH | FLAG_THREAD, 1); + set_comp_log(PDCP, LOG_INFO, LOG_HIGH, 1); + set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1); + set_comp_log(RRC, LOG_INFO, LOG_HIGH, 1); #if defined(ENABLE_ITTI) - set_comp_log(EMU, LOG_INFO, LOG_MED, 1); + set_comp_log(EMU, LOG_INFO, LOG_MED, 1); # if defined(ENABLE_USE_MME) - set_comp_log(NAS, LOG_INFO, LOG_HIGH, 1); + set_comp_log(NAS, LOG_INFO, LOG_HIGH, 1); # endif #endif - } else { - printf("configuring for eNB\n"); - - set_comp_log(HW, hw_log_level, hw_log_verbosity, 1); - set_comp_log(PHY, phy_log_level, phy_log_verbosity, 1); - if (opt_enabled == 1 ) - set_comp_log(OPT, opt_log_level, opt_log_verbosity, 1); - set_comp_log(MAC, mac_log_level, mac_log_verbosity, 1); - set_comp_log(RLC, rlc_log_level, rlc_log_verbosity, 1); - set_comp_log(PDCP, pdcp_log_level, pdcp_log_verbosity, 1); - set_comp_log(RRC, rrc_log_level, rrc_log_verbosity, 1); + } else { + printf("configuring for eNB\n"); + + set_comp_log(HW, hw_log_level, hw_log_verbosity, 1); + set_comp_log(PHY, phy_log_level, phy_log_verbosity, 1); + if (opt_enabled == 1 ) + set_comp_log(OPT, opt_log_level, opt_log_verbosity, 1); + set_comp_log(MAC, mac_log_level, mac_log_verbosity, 1); + set_comp_log(RLC, rlc_log_level, rlc_log_verbosity, 1); + set_comp_log(PDCP, pdcp_log_level, pdcp_log_verbosity, 1); + set_comp_log(RRC, rrc_log_level, rrc_log_verbosity, 1); #if defined(ENABLE_ITTI) - set_comp_log(EMU, LOG_INFO, LOG_MED, 1); + set_comp_log(EMU, LOG_INFO, LOG_MED, 1); # if defined(ENABLE_USE_MME) - set_comp_log(UDP_, udp_log_level, udp_log_verbosity, 1); - set_comp_log(GTPU, gtpu_log_level, gtpu_log_verbosity, 1); - set_comp_log(S1AP, LOG_DEBUG, LOG_HIGH, 1); - set_comp_log(SCTP, LOG_INFO, LOG_HIGH, 1); + set_comp_log(UDP_, udp_log_level, udp_log_verbosity, 1); + set_comp_log(GTPU, gtpu_log_level, gtpu_log_verbosity, 1); + set_comp_log(S1AP, LOG_DEBUG, LOG_HIGH, 1); + set_comp_log(SCTP, LOG_INFO, LOG_HIGH, 1); # endif #if defined(ENABLE_SECURITY) - set_comp_log(OSA, osa_log_level, osa_log_verbosity, 1); + set_comp_log(OSA, osa_log_level, osa_log_verbosity, 1); #endif #endif #ifdef LOCALIZATION - set_comp_log(LOCALIZE, LOG_DEBUG, LOG_LOW, 1); - set_component_filelog(LOCALIZE); + set_comp_log(LOCALIZE, LOG_DEBUG, LOG_LOW, 1); + set_component_filelog(LOCALIZE); #endif - set_comp_log(ENB_APP, LOG_INFO, LOG_HIGH, 1); - set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1); + set_comp_log(ENB_APP, LOG_INFO, LOG_HIGH, 1); + set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1); - if (online_log_messages == 1) { - set_component_filelog(RRC); - set_component_filelog(PDCP); + if (online_log_messages == 1) { + set_component_filelog(RRC); + set_component_filelog(PDCP); + } } - } - if (ouput_vcd) { - if (UE_flag==1) - VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd"); - else - VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd"); - } + if (ouput_vcd) { + if (UE_flag==1) + VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd"); + else + VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd"); + } - if (opp_enabled ==1){ - reset_opp_meas(); - } - cpuf=get_cpu_freq_GHz(); + if (opp_enabled ==1) { + reset_opp_meas(); + } + cpuf=get_cpu_freq_GHz(); #if defined(ENABLE_ITTI) - if (UE_flag == 1) { - log_set_instance_type (LOG_INSTANCE_UE); - } else { - log_set_instance_type (LOG_INSTANCE_ENB); - } + if (UE_flag == 1) { + log_set_instance_type (LOG_INSTANCE_UE); + } else { + log_set_instance_type (LOG_INSTANCE_ENB); + } + + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file); - - // initialize mscgen log after ITTI - MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); + // initialize mscgen log after ITTI + MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); #endif - - if (opt_type != OPT_NONE) { - radio_type_t radio_type; - if (frame_parms[0]->frame_type == FDD) - radio_type = RADIO_TYPE_FDD; - else - radio_type = RADIO_TYPE_TDD; + if (opt_type != OPT_NONE) { + radio_type_t radio_type; - if (init_opt(in_path, in_ip, NULL, radio_type) == -1) - LOG_E(OPT,"failed to run OPT \n"); - } + if (frame_parms[0]->frame_type == FDD) + radio_type = RADIO_TYPE_FDD; + else + radio_type = RADIO_TYPE_TDD; + + if (init_opt(in_path, in_ip, NULL, radio_type) == -1) + LOG_E(OPT,"failed to run OPT \n"); + } #ifdef PDCP_USE_NETLINK - netlink_init(); + netlink_init(); #if defined(PDCP_USE_NETLINK_QUEUES) - pdcp_netlink_init(); + pdcp_netlink_init(); #endif #endif #if !defined(ENABLE_ITTI) - // to make a graceful exit when ctrl-c is pressed - signal(SIGSEGV, signal_handler); - signal(SIGINT, signal_handler); + // to make a graceful exit when ctrl-c is pressed + signal(SIGSEGV, signal_handler); + signal(SIGINT, signal_handler); #endif - check_clock(); + check_clock(); + +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); // init the parameters for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (UE_flag==1) { - frame_parms[CC_id]->nb_antennas_tx = 1; - frame_parms[CC_id]->nb_antennas_rx = 1; + frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx; + frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx; frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later + + LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx); } init_ul_hopping(frame_parms[CC_id]); @@ -1560,453 +1543,450 @@ int main( int argc, char **argv ) } - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - //init prach for openair1 test - - // prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type); - // N_ZC = (prach_fmt <4)?839:139; - } - - if (UE_flag==1) { - NB_UE_INST=1; - NB_INST=1; - - PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)); - PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs); for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + //init prach for openair1 test - PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag); - UE[CC_id] = PHY_vars_UE_g[0][CC_id]; - printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]); - - if (phy_test==1) - UE[CC_id]->mac_enabled = 0; - else - UE[CC_id]->mac_enabled = 1; - - if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode - for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { - UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; - UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; - UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; - - UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0; - UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3); - UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4; - } - } - - UE[CC_id]->UE_scan = UE_scan; - UE[CC_id]->UE_scan_carrier = UE_scan_carrier; - UE[CC_id]->mode = mode; - printf("UE[%d]->mode = %d\n",CC_id,mode); - - compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common, - UE[CC_id]->frame_parms.frame_type, - UE[CC_id]->X_u); - - if (UE[CC_id]->mac_enabled == 1) - UE[CC_id]->pdcch_vars[0]->crnti = 0x1234; - else - UE[CC_id]->pdcch_vars[0]->crnti = 0x1235; - - UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; - UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; - - if (frame_parms[CC_id]->frame_type==FDD) { - UE[CC_id]->N_TA_offset = 0; - } - else { - if (frame_parms[CC_id]->N_RB_DL == 100) - UE[CC_id]->N_TA_offset = 624; - else if (frame_parms[CC_id]->N_RB_DL == 50) - UE[CC_id]->N_TA_offset = 624/2; - else if (frame_parms[CC_id]->N_RB_DL == 25) - UE[CC_id]->N_TA_offset = 624/4; - } - + // prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type); + // N_ZC = (prach_fmt <4)?839:139; } - // printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_poHwer,tx_max_power)); - } else { - //this is eNB - PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**)); - PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*)); + if (UE_flag==1) { + NB_UE_INST=1; + NB_INST=1; + + PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)); + PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs); + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + + PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag); + UE[CC_id] = PHY_vars_UE_g[0][CC_id]; + printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]); + + if (phy_test==1) + UE[CC_id]->mac_enabled = 0; + else + UE[CC_id]->mac_enabled = 1; + + if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode + for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { + UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; + UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; + UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; + + UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0; + UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3); + UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4; + } + } + + UE[CC_id]->UE_scan = UE_scan; + UE[CC_id]->UE_scan_carrier = UE_scan_carrier; + UE[CC_id]->mode = mode; + printf("UE[%d]->mode = %d\n",CC_id,mode); + + compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common, + UE[CC_id]->frame_parms.frame_type, + UE[CC_id]->X_u); + + if (UE[CC_id]->mac_enabled == 1) + { + UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234; + UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234; + } + else + { + UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235; + UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235; + } + + UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; + UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; + + if (frame_parms[CC_id]->frame_type==FDD) { + UE[CC_id]->N_TA_offset = 0; + } else { + if (frame_parms[CC_id]->N_RB_DL == 100) + UE[CC_id]->N_TA_offset = 624; + else if (frame_parms[CC_id]->N_RB_DL == 50) + UE[CC_id]->N_TA_offset = 624/2; + else if (frame_parms[CC_id]->N_RB_DL == 25) + UE[CC_id]->N_TA_offset = 624/4; + } - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,node_function[CC_id],abstraction_flag); - PHY_vars_eNB_g[0][CC_id]->ue_dl_rb_alloc=0x1fff; - PHY_vars_eNB_g[0][CC_id]->target_ue_dl_mcs=target_dl_mcs; - PHY_vars_eNB_g[0][CC_id]->ue_ul_nb_rb=6; - PHY_vars_eNB_g[0][CC_id]->target_ue_ul_mcs=target_ul_mcs; - // initialization for phy-test - for (k=0;k<NUMBER_OF_UE_MAX;k++) { - PHY_vars_eNB_g[0][CC_id]->transmission_mode[k] = transmission_mode; - if (transmission_mode==7) - lte_gold_ue_spec_port5(PHY_vars_eNB_g[0][CC_id]->lte_gold_uespec_port5_table[k],frame_parms[CC_id]->Nid_cell,0x1235+k); - } - if ((transmission_mode==1) || (transmission_mode==7)) { - for (j=0; j<frame_parms[CC_id]->nb_antennas_tx; j++) - for (re=0; re<frame_parms[CC_id]->ofdm_symbol_size; re++) - PHY_vars_eNB_g[0][CC_id]->common_vars.beam_weights[0][0][j][re] = 0x00007fff/frame_parms[CC_id]->nb_antennas_tx; - } + } - if (phy_test==1) PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0; - else PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1; - - if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) { //set default parameters for testing mode - for (i=0; i<NUMBER_OF_UE_MAX; i++) { - PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; - PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; - PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; - - PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i; - PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3); - PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4; - } - } - - compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->frame_parms.prach_config_common, - PHY_vars_eNB_g[0][CC_id]->frame_parms.frame_type, - PHY_vars_eNB_g[0][CC_id]->X_u); - - - PHY_vars_eNB_g[0][CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0]; + // printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_poHwer,tx_max_power)); + } else { + //this is eNB + PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**)); + PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*)); + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,node_function[CC_id],abstraction_flag); + PHY_vars_eNB_g[0][CC_id]->ue_dl_rb_alloc=0x1fff; + PHY_vars_eNB_g[0][CC_id]->target_ue_dl_mcs=target_dl_mcs; + PHY_vars_eNB_g[0][CC_id]->ue_ul_nb_rb=6; + PHY_vars_eNB_g[0][CC_id]->target_ue_ul_mcs=target_ul_mcs; + // initialization for phy-test + for (k=0; k<NUMBER_OF_UE_MAX; k++) { + PHY_vars_eNB_g[0][CC_id]->transmission_mode[k] = transmission_mode; + if (transmission_mode==7) + lte_gold_ue_spec_port5(PHY_vars_eNB_g[0][CC_id]->lte_gold_uespec_port5_table[k],frame_parms[CC_id]->Nid_cell,0x1235+k); + } + if ((transmission_mode==1) || (transmission_mode==7)) { + for (j=0; j<frame_parms[CC_id]->nb_antennas_tx; j++) + for (re=0; re<frame_parms[CC_id]->ofdm_symbol_size; re++) + PHY_vars_eNB_g[0][CC_id]->common_vars.beam_weights[0][0][j][re] = 0x00007fff/frame_parms[CC_id]->nb_antennas_tx; + } + + if (phy_test==1) PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0; + else PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1; + + if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) { //set default parameters for testing mode + for (i=0; i<NUMBER_OF_UE_MAX; i++) { + PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; + PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; + PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; + + PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i; + PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3); + PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4; + } + } + + compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->frame_parms.prach_config_common, + PHY_vars_eNB_g[0][CC_id]->frame_parms.frame_type, + PHY_vars_eNB_g[0][CC_id]->X_u); + + + PHY_vars_eNB_g[0][CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0]; + + if (frame_parms[CC_id]->frame_type==FDD) { + PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; + } else { + if (frame_parms[CC_id]->N_RB_DL == 100) + PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624; + else if (frame_parms[CC_id]->N_RB_DL == 50) + PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2; + else if (frame_parms[CC_id]->N_RB_DL == 25) + PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4; + } - if (frame_parms[CC_id]->frame_type==FDD) { - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; - } - else { - if (frame_parms[CC_id]->N_RB_DL == 100) - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624; - else if (frame_parms[CC_id]->N_RB_DL == 50) - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2; - else if (frame_parms[CC_id]->N_RB_DL == 25) - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4; - } + } - } - - NB_eNB_INST=1; - NB_INST=1; + NB_eNB_INST=1; + NB_INST=1; - } + } - fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); - cpuf=get_cpu_freq_GHz(); + fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); + cpuf=get_cpu_freq_GHz(); - dump_frame_parms(frame_parms[0]); + dump_frame_parms(frame_parms[0]); - init_openair0(); + init_openair0(); #ifndef DEADLINE_SCHEDULER - /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */ - - cpu_set_t cpuset; - int s; - char cpu_affinity[1024]; - CPU_ZERO(&cpuset); + /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */ + + cpu_set_t cpuset; + int s; + char cpu_affinity[1024]; + CPU_ZERO(&cpuset); #ifdef CPU_AFFINITY - if (get_nprocs() > 2) - { - CPU_SET(0, &cpuset); - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n"); + if (get_nprocs() > 2) { + CPU_SET(0, &cpuset); + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) { + perror( "pthread_setaffinity_np"); + exit_fun("Error setting processor affinity"); + } + LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n"); } #endif - /* Check the actual affinity mask assigned to the thread */ - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); + /* Check the actual affinity mask assigned to the thread */ + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) { + perror( "pthread_getaffinity_np"); + exit_fun("Error getting processor affinity "); } - memset(cpu_affinity, 0 , sizeof(cpu_affinity)); - for (int j = 0; j < CPU_SETSIZE; j++) - { - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf(temp, " CPU_%d ", j); - strcat(cpu_affinity, temp); - } + memset(cpu_affinity, 0 , sizeof(cpu_affinity)); + for (int j = 0; j < CPU_SETSIZE; j++) { + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf(temp, " CPU_%d ", j); + strcat(cpu_affinity, temp); + } } - LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity); + LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity); #endif - - openair0_cfg[0].log_level = glog_level; - + openair0_cfg[0].log_level = glog_level; - int eMBMS_active=0; - if (node_function[0] <= NGFI_RAU_IF4p5) { // don't initialize L2 for RRU - LOG_I(PHY,"Intializing L2\n"); - mac_xface = malloc(sizeof(MAC_xface)); - l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL, - 0,// cba_group_active - 0); // HO flag - mac_xface->macphy_exit = &exit_fun; - } - else if (node_function[0] == NGFI_RRU_IF4p5) { // Initialize PRACH in this case - } + + int eMBMS_active=0; + if (node_function[0] <= NGFI_RAU_IF4p5) { // don't initialize L2 for RRU + LOG_I(PHY,"Intializing L2\n"); + mac_xface = malloc(sizeof(MAC_xface)); + l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL, + 0,// cba_group_active + 0); // HO flag + mac_xface->macphy_exit = &exit_fun; + } else if (node_function[0] == NGFI_RRU_IF4p5) { // Initialize PRACH in this case + + } #if defined(ENABLE_ITTI) - if ((UE_flag == 1)|| - (node_function[0]<NGFI_RAU_IF4p5)) - // don't create if node doesn't connect to RRC/S1/GTP - if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) { - printf("cannot create ITTI tasks\n"); - exit(-1); // need a softer mode - } + if ((UE_flag == 1)|| + ((node_function[0]<NGFI_RAU_IF4p5)&&(phy_test==0))) + // don't create if node doesn't connect to RRC/S1/GTP + if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) { + printf("cannot create ITTI tasks\n"); + exit(-1); // need a softer mode + } - printf("ITTI tasks created\n"); + printf("ITTI tasks created\n"); #endif - if (phy_test==0) { - if (UE_flag==1) { - printf("Filling UE band info\n"); - fill_ue_band_info(); - mac_xface->dl_phy_sync_success (0, 0, 0, 1); - } else if (node_function[0]>NGFI_RRU_IF4p5) - mac_xface->mrbch_phy_sync_failure (0, 0, 0); - } + if (phy_test==0) { + if (UE_flag==1) { + printf("Filling UE band info\n"); + fill_ue_band_info(); + mac_xface->dl_phy_sync_success (0, 0, 0, 1); + } else if (node_function[0]>NGFI_RRU_IF4p5) + mac_xface->mrbch_phy_sync_failure (0, 0, 0); + } - mlockall(MCL_CURRENT | MCL_FUTURE); + mlockall(MCL_CURRENT | MCL_FUTURE); - pthread_cond_init(&sync_cond,NULL); - pthread_mutex_init(&sync_mutex, NULL); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); #ifdef XFORMS - int UE_id; - - if (do_forms==1) { - fl_initialize (&argc, argv, NULL, 0, 0); - - if (UE_flag==0) { - form_stats_l2 = create_form_stats_form(); - fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats"); - form_stats = create_form_stats_form(); - fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); - - for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - form_enb[CC_id][UE_id] = create_lte_phy_scope_enb(); - sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id); - fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - - if (otg_enabled) { - fl_set_button(form_enb[CC_id][UE_id]->button_0,1); - fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON"); - } else { - fl_set_button(form_enb[CC_id][UE_id]->button_0,0); - fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF"); - } - } // CC_id - } // UE_id - } else { - form_stats = create_form_stats_form(); - fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); - UE_id = 0; - form_ue[UE_id] = create_lte_phy_scope_ue(); - sprintf (title, "LTE DL SCOPE UE"); - fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - - /* - if (openair_daq_vars.use_ia_receiver) { - fl_set_button(form_ue[UE_id]->button_0,1); - fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON"); - } else { - fl_set_button(form_ue[UE_id]->button_0,0); - fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); - }*/ - fl_set_button(form_ue[UE_id]->button_0,0); - fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); - } + int UE_id; + + if (do_forms==1) { + fl_initialize (&argc, argv, NULL, 0, 0); + + if (UE_flag==0) { + form_stats_l2 = create_form_stats_form(); + fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats"); + form_stats = create_form_stats_form(); + fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); + + for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + form_enb[CC_id][UE_id] = create_lte_phy_scope_enb(); + sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id); + fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + + if (otg_enabled) { + fl_set_button(form_enb[CC_id][UE_id]->button_0,1); + fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON"); + } else { + fl_set_button(form_enb[CC_id][UE_id]->button_0,0); + fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF"); + } + } // CC_id + } // UE_id + } else { + form_stats = create_form_stats_form(); + fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); + UE_id = 0; + form_ue[UE_id] = create_lte_phy_scope_ue(); + sprintf (title, "LTE DL SCOPE UE"); + fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + + /* + if (openair_daq_vars.use_ia_receiver) { + fl_set_button(form_ue[UE_id]->button_0,1); + fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON"); + } else { + fl_set_button(form_ue[UE_id]->button_0,0); + fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); + }*/ + fl_set_button(form_ue[UE_id]->button_0,0); + fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); + } - ret = pthread_create(&forms_thread, NULL, scope_thread, NULL); + ret = pthread_create(&forms_thread, NULL, scope_thread, NULL); - if (ret == 0) - pthread_setname_np( forms_thread, "xforms" ); + if (ret == 0) + pthread_setname_np( forms_thread, "xforms" ); - printf("Scope thread created, ret=%d\n",ret); - } + printf("Scope thread created, ret=%d\n",ret); + } #endif - rt_sleep_ns(10*100000000ULL); + rt_sleep_ns(10*100000000ULL); - // start the main thread - if (UE_flag == 1) { - init_UE(1); - number_of_cards = 1; - - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - PHY_vars_UE_g[0][CC_id]->rf_map.card=0; - PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; - } - } - else { - printf("Initializing eNB threads\n"); - init_eNB(node_function,node_timing,1,eth_params,single_thread_flag,wait_for_sync); + // start the main thread + if (UE_flag == 1) { + init_UE(1); + number_of_cards = 1; - number_of_cards = 1; - - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - PHY_vars_eNB_g[0][CC_id]->rf_map.card=0; - PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_UE_g[0][CC_id]->rf_map.card=0; + PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; + } + } else { + printf("Initializing eNB threads\n"); + init_eNB(node_function,node_timing,1,eth_params,single_thread_flag,wait_for_sync); + + number_of_cards = 1; + + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_eNB_g[0][CC_id]->rf_map.card=0; + PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; + } } - } - // connect the TX/RX buffers - if (UE_flag==1) { + // connect the TX/RX buffers + if (UE_flag==1) { + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - for (CC_id=0;CC_id<MAX_NUM_CCs; CC_id++) { - #ifdef OAI_USRP - UE[CC_id]->hw_timing_advance = timing_advance; + UE[CC_id]->hw_timing_advance = timing_advance; #else - UE[CC_id]->hw_timing_advance = 160; + UE[CC_id]->hw_timing_advance = 160; #endif - } - if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) { - printf("Error setting up eNB buffer\n"); - exit(-1); - } + } + if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) { + printf("Error setting up eNB buffer\n"); + exit(-1); + } - if (input_fd) { - printf("Reading in from file to antenna buffer %d\n",0); - if (fread(UE[0]->common_vars.rxdata[0], - sizeof(int32_t), - frame_parms[0]->samples_per_tti*10, - input_fd) != frame_parms[0]->samples_per_tti*10) - printf("error reading from file\n"); - } - //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; - } else { + if (input_fd) { + printf("Reading in from file to antenna buffer %d\n",0); + if (fread(UE[0]->common_vars.rxdata[0], + sizeof(int32_t), + frame_parms[0]->samples_per_tti*10, + input_fd) != frame_parms[0]->samples_per_tti*10) + printf("error reading from file\n"); + } + //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; + } else { - printf("Setting eNB buffer to all-RX\n"); + printf("Setting eNB buffer to all-RX\n"); - // Set LSBs for antenna switch (ExpressMIMO) - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0; - for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++) - for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++) - PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; + // Set LSBs for antenna switch (ExpressMIMO) + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0; + for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++) + for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++) + PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; + } } - } - sleep(3); + sleep(3); - printf("Sending sync to all threads\n"); + printf("Sending sync to all threads\n"); - pthread_mutex_lock(&sync_mutex); - sync_var=0; - pthread_cond_broadcast(&sync_cond); - pthread_mutex_unlock(&sync_mutex); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); - // wait for end of program - printf("TYPE <CTRL-C> TO TERMINATE\n"); - //getchar(); + // wait for end of program + printf("TYPE <CTRL-C> TO TERMINATE\n"); + //getchar(); #if defined(ENABLE_ITTI) - printf("Entering ITTI signals handler\n"); - itti_wait_tasks_end(); - oai_exit=1; + printf("Entering ITTI signals handler\n"); + itti_wait_tasks_end(); + oai_exit=1; #else - while (oai_exit==0) - rt_sleep_ns(100000000ULL); + while (oai_exit==0) + rt_sleep_ns(100000000ULL); #endif - // stop threads + // stop threads #ifdef XFORMS - printf("waiting for XFORMS thread\n"); + printf("waiting for XFORMS thread\n"); - if (do_forms==1) { - pthread_join(forms_thread,&status); - fl_hide_form(form_stats->stats_form); - fl_free_form(form_stats->stats_form); + if (do_forms==1) { + pthread_join(forms_thread,&status); + fl_hide_form(form_stats->stats_form); + fl_free_form(form_stats->stats_form); - if (UE_flag==1) { - fl_hide_form(form_ue[0]->lte_phy_scope_ue); - fl_free_form(form_ue[0]->lte_phy_scope_ue); - } else { - fl_hide_form(form_stats_l2->stats_form); - fl_free_form(form_stats_l2->stats_form); - - for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb); - fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb); - } - } + if (UE_flag==1) { + fl_hide_form(form_ue[0]->lte_phy_scope_ue); + fl_free_form(form_ue[0]->lte_phy_scope_ue); + } else { + fl_hide_form(form_stats_l2->stats_form); + fl_free_form(form_stats_l2->stats_form); + + for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb); + fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb); + } + } + } } - } #endif - printf("stopping MODEM threads\n"); + printf("stopping MODEM threads\n"); - // cleanup - if (UE_flag == 1) { - } else { - stop_eNB(1); - } + // cleanup + if (UE_flag == 1) { + } else { + stop_eNB(1); + } - pthread_cond_destroy(&sync_cond); - pthread_mutex_destroy(&sync_mutex); + pthread_cond_destroy(&sync_cond); + pthread_mutex_destroy(&sync_mutex); - // *** Handle per CC_id openair0 - if (UE_flag==1) { - if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func) - PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice); - } - else { - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); - if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + // *** Handle per CC_id openair0 + if (UE_flag==1) { + if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func) + PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice); + } else { + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } } - } - if (ouput_vcd) - VCD_SIGNAL_DUMPER_CLOSE(); + if (ouput_vcd) + VCD_SIGNAL_DUMPER_CLOSE(); - if (opt_enabled == 1) - terminate_opt(); + if (opt_enabled == 1) + terminate_opt(); - logClean(); + logClean(); - return 0; + return 0; } diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h new file mode 100644 index 0000000000000000000000000000000000000000..b438d9eee2fc04cb630e78a4d80d33b1b986669f --- /dev/null +++ b/targets/RT/USER/lte-softmodem.h @@ -0,0 +1,91 @@ +#ifndef LTE_SOFTMODEM_H +#define LTE_SOFTMODEM_H + +#define _GNU_SOURCE +#include <execinfo.h> +#include <fcntl.h> +#include <getopt.h> +#include <linux/sched.h> +#include "rt_wrapper.h" +#include <sched.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syscall.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/sysinfo.h> +#include <sys/types.h> +#include <unistd.h> + +#include <sys/sysinfo.h> +#include "rt_wrapper.h" +#include "../../ARCH/COMMON/common_lib.h" +#undef MALLOC +#include "assertions.h" +#include "msc.h" +#include "PHY/types.h" +#include "PHY/defs.h" +#include "SIMULATION/ETH_TRANSPORT/proto.h" + +#if defined(ENABLE_ITTI) +#if defined(ENABLE_USE_MME) +#include "s1ap_eNB.h" +#ifdef PDCP_USE_NETLINK +#include "SIMULATION/ETH_TRANSPORT/proto.h" +#endif +#endif +#endif + +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; + + +extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +extern int rx_input_level_dBm; +extern uint8_t exit_missed_slots; +extern uint64_t num_missed_slots; // counter for the number of missed slots + +extern int oaisim_flag; +extern volatile int oai_exit; + +extern openair0_config_t openair0_cfg[MAX_CARDS]; +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; +extern int transmission_mode; +extern double cpuf; + +#if defined(ENABLE_ITTI) +extern volatile int start_eNB; +extern volatile int start_UE; +#endif + +#include "threads_t.h" +extern threads_t threads; + +extern void exit_fun(const char* s); +// In lte-enb.c +extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg); +extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int,int); +extern void stop_eNB(int); +extern void kill_eNB_proc(int inst); + +// In lte-ue.c +extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg); +extern void fill_ue_band_info(void); +extern void init_UE(int); +extern void reset_opp_meas(void); +extern void print_opp_meas(void); + +extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); +extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *); +extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *); + +#endif diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index ed93f44aa954dc7382d863ba895ed75faab15be1..f07a0628f8979d6093ac92e8cabbbd81a0d4daff 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -29,29 +29,10 @@ * \note * \warning */ -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sched.h> -#include <linux/sched.h> -#include <signal.h> -#include <execinfo.h> -#include <getopt.h> -#include <syscall.h> -#include <sys/sysinfo.h> +#include "lte-softmodem.h" #include "rt_wrapper.h" -#include "assertions.h" -#include "PHY/types.h" -#include "PHY/defs.h" #ifdef OPENAIR2 #include "LAYER2/MAC/defs.h" #include "RRC/LITE/extern.h" @@ -61,8 +42,6 @@ #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all -#include "../../ARCH/COMMON/common_lib.h" - #include "PHY/extern.h" #include "SCHED/extern.h" #include "LAYER2/MAC/extern.h" @@ -77,139 +56,146 @@ #include "T.h" +extern double cpuf; + #define FRAME_PERIOD 100000000ULL #define DAQ_PERIOD 66667ULL +#define FIFO_PRIORITY 40 typedef enum { - pss=0, - pbch=1, - si=2 + pss=0, + pbch=1, + si=2 } sync_mode_t; -void init_UE_threads(int nb_inst); +void init_UE_threads(PHY_VARS_UE *UE); void *UE_thread(void *arg); void init_UE(int nb_inst); -extern pthread_cond_t sync_cond; -extern pthread_mutex_t sync_mutex; -extern int sync_var; - - -extern openair0_config_t openair0_cfg[MAX_CARDS]; -extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -extern int oai_exit; - int32_t **rxdata; int32_t **txdata; -//extern unsigned int tx_forward_nsamps; -//extern int tx_delay; - -extern int rx_input_level_dBm; -extern uint8_t exit_missed_slots; -extern uint64_t num_missed_slots; // counter for the number of missed slots - -extern int oaisim_flag; - -extern void exit_fun(const char* s); - #define KHz (1000UL) -#define MHz (1000 * KHz) +#define MHz (1000*KHz) typedef struct eutra_band_s { - int16_t band; - uint32_t ul_min; - uint32_t ul_max; - uint32_t dl_min; - uint32_t dl_max; - lte_frame_type_t frame_type; + int16_t band; + uint32_t ul_min; + uint32_t ul_max; + uint32_t dl_min; + uint32_t dl_max; + lte_frame_type_t frame_type; } eutra_band_t; typedef struct band_info_s { - int nbands; - eutra_band_t band_info[100]; + int nbands; + eutra_band_t band_info[100]; } band_info_t; band_info_t bands_to_scan; static const eutra_band_t eutra_bands[] = { - { 1, 1920 * MHz, 1980 * MHz, 2110 * MHz, 2170 * MHz, FDD}, - { 2, 1850 * MHz, 1910 * MHz, 1930 * MHz, 1990 * MHz, FDD}, - { 3, 1710 * MHz, 1785 * MHz, 1805 * MHz, 1880 * MHz, FDD}, - { 4, 1710 * MHz, 1755 * MHz, 2110 * MHz, 2155 * MHz, FDD}, - { 5, 824 * MHz, 849 * MHz, 869 * MHz, 894 * MHz, FDD}, - { 6, 830 * MHz, 840 * MHz, 875 * MHz, 885 * MHz, FDD}, - { 7, 2500 * MHz, 2570 * MHz, 2620 * MHz, 2690 * MHz, FDD}, - { 8, 880 * MHz, 915 * MHz, 925 * MHz, 960 * MHz, FDD}, - { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD}, - {10, 1710 * MHz, 1770 * MHz, 2110 * MHz, 2170 * MHz, FDD}, - {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD}, - {12, 698 * MHz, 716 * MHz, 728 * MHz, 746 * MHz, FDD}, - {13, 777 * MHz, 787 * MHz, 746 * MHz, 756 * MHz, FDD}, - {14, 788 * MHz, 798 * MHz, 758 * MHz, 768 * MHz, FDD}, - {17, 704 * MHz, 716 * MHz, 734 * MHz, 746 * MHz, FDD}, - {20, 832 * MHz, 862 * MHz, 791 * MHz, 821 * MHz, FDD}, - {22, 3510 * MHz, 3590 * MHz, 3410 * MHz, 3490 * MHz, FDD}, - {33, 1900 * MHz, 1920 * MHz, 1900 * MHz, 1920 * MHz, TDD}, - {34, 2010 * MHz, 2025 * MHz, 2010 * MHz, 2025 * MHz, TDD}, - {35, 1850 * MHz, 1910 * MHz, 1850 * MHz, 1910 * MHz, TDD}, - {36, 1930 * MHz, 1990 * MHz, 1930 * MHz, 1990 * MHz, TDD}, - {37, 1910 * MHz, 1930 * MHz, 1910 * MHz, 1930 * MHz, TDD}, - {38, 2570 * MHz, 2620 * MHz, 2570 * MHz, 2630 * MHz, TDD}, - {39, 1880 * MHz, 1920 * MHz, 1880 * MHz, 1920 * MHz, TDD}, - {40, 2300 * MHz, 2400 * MHz, 2300 * MHz, 2400 * MHz, TDD}, - {41, 2496 * MHz, 2690 * MHz, 2496 * MHz, 2690 * MHz, TDD}, - {42, 3400 * MHz, 3600 * MHz, 3400 * MHz, 3600 * MHz, TDD}, - {43, 3600 * MHz, 3800 * MHz, 3600 * MHz, 3800 * MHz, TDD}, - {44, 703 * MHz, 803 * MHz, 703 * MHz, 803 * MHz, TDD}, + { 1, 1920 * MHz, 1980 * MHz, 2110 * MHz, 2170 * MHz, FDD}, + { 2, 1850 * MHz, 1910 * MHz, 1930 * MHz, 1990 * MHz, FDD}, + { 3, 1710 * MHz, 1785 * MHz, 1805 * MHz, 1880 * MHz, FDD}, + { 4, 1710 * MHz, 1755 * MHz, 2110 * MHz, 2155 * MHz, FDD}, + { 5, 824 * MHz, 849 * MHz, 869 * MHz, 894 * MHz, FDD}, + { 6, 830 * MHz, 840 * MHz, 875 * MHz, 885 * MHz, FDD}, + { 7, 2500 * MHz, 2570 * MHz, 2620 * MHz, 2690 * MHz, FDD}, + { 8, 880 * MHz, 915 * MHz, 925 * MHz, 960 * MHz, FDD}, + { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD}, + {10, 1710 * MHz, 1770 * MHz, 2110 * MHz, 2170 * MHz, FDD}, + {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD}, + {12, 698 * MHz, 716 * MHz, 728 * MHz, 746 * MHz, FDD}, + {13, 777 * MHz, 787 * MHz, 746 * MHz, 756 * MHz, FDD}, + {14, 788 * MHz, 798 * MHz, 758 * MHz, 768 * MHz, FDD}, + {17, 704 * MHz, 716 * MHz, 734 * MHz, 746 * MHz, FDD}, + {20, 832 * MHz, 862 * MHz, 791 * MHz, 821 * MHz, FDD}, + {22, 3510 * MHz, 3590 * MHz, 3410 * MHz, 3490 * MHz, FDD}, + {33, 1900 * MHz, 1920 * MHz, 1900 * MHz, 1920 * MHz, TDD}, + {34, 2010 * MHz, 2025 * MHz, 2010 * MHz, 2025 * MHz, TDD}, + {35, 1850 * MHz, 1910 * MHz, 1850 * MHz, 1910 * MHz, TDD}, + {36, 1930 * MHz, 1990 * MHz, 1930 * MHz, 1990 * MHz, TDD}, + {37, 1910 * MHz, 1930 * MHz, 1910 * MHz, 1930 * MHz, TDD}, + {38, 2570 * MHz, 2620 * MHz, 2570 * MHz, 2630 * MHz, TDD}, + {39, 1880 * MHz, 1920 * MHz, 1880 * MHz, 1920 * MHz, TDD}, + {40, 2300 * MHz, 2400 * MHz, 2300 * MHz, 2400 * MHz, TDD}, + {41, 2496 * MHz, 2690 * MHz, 2496 * MHz, 2690 * MHz, TDD}, + {42, 3400 * MHz, 3600 * MHz, 3400 * MHz, 3600 * MHz, TDD}, + {43, 3600 * MHz, 3800 * MHz, 3600 * MHz, 3800 * MHz, TDD}, + {44, 703 * MHz, 803 * MHz, 703 * MHz, 803 * MHz, TDD}, }; -pthread_t main_ue_thread; -pthread_attr_t attr_UE_thread; -struct sched_param sched_param_UE_thread; +void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) { -void init_UE(int nb_inst) { +#ifdef DEADLINE_SCHEDULER + if (sched_runtime!=0) { + struct sched_attr attr= {0}; + attr.size = sizeof(attr); + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = sched_runtime; + attr.sched_deadline = sched_deadline; + attr.sched_period = 0; + AssertFatal(sched_setattr(0, &attr, 0) == 0, + "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno)); + LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n", + name, (unsigned long)gettid(), sched_getcpu()); + } - int error_code; - int inst; - PHY_VARS_UE *UE; - int ret; +#else + if (CPU_COUNT(cpuset) > 0) + AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), ""); + struct sched_param sp; + sp.sched_priority = sched_fifo; + AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0, + "Can't set thread priority, Are you root?\n"); + /* Check the actual affinity mask assigned to the thread */ + cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE); + if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) { + char txt[512]={0}; + for (int j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, cset)) + sprintf(txt+strlen(txt), " %d ", j); + printf("CPU Affinity of thread %s is %s\n", name, txt); + } + CPU_FREE(cset); +#endif - for (inst=0;inst<nb_inst;inst++) { - printf("Intializing UE Threads for instance %d ...\n",inst); - init_UE_threads(inst); - sleep(1); - UE = PHY_vars_UE_g[inst][0]; + // Lock memory from swapping. This is a process wide call (not constraint to this thread). + mlockall(MCL_CURRENT | MCL_FUTURE); + pthread_setname_np( pthread_self(), name ); + + // LTS: this sync stuff should be wrong + printf("waiting for sync (%s)\n",name); + pthread_mutex_lock(&sync_mutex); + printf("Locked sync_mutex, waiting (%s)\n",name); + while (sync_var<0) + pthread_cond_wait(&sync_cond, &sync_mutex); + pthread_mutex_unlock(&sync_mutex); + printf("started %s as PID: %ld\n",name, gettid()); +} - if (oaisim_flag == 0) { - ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]); - if (ret !=0){ - exit_fun("Error loading device library"); - } - } - UE->rfdevice.host_type = BBU_HOST; +void init_UE(int nb_inst) +{ + int inst; + for (inst=0; inst < nb_inst; inst++) { // UE->rfdevice.type = NONE_DEV; - error_code = pthread_create(&UE->proc.pthread_ue, &UE->proc.attr_ue, UE_thread, NULL); - - if (error_code!= 0) { - LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code); - return; - } else { - LOG_D(HW, "[lte-softmodem.c] Allocate UE_thread successful\n" ); - pthread_setname_np( UE->proc.pthread_ue, "main UE" ); - } + PHY_VARS_UE *UE = PHY_vars_UE_g[inst][0]; + AssertFatal(0 == pthread_create(&UE->proc.pthread_ue, + &UE->proc.attr_ue, + UE_thread, + (void*)UE), ""); } - printf("UE threads created\n"); -#ifdef USE_MME - + printf("UE threads created by %ld\n", gettid()); +#if 0 +#if defined(ENABLE_USE_MME) + extern volatile int start_UE; while (start_UE == 0) { sleep(1); } - #endif - +#endif } /*! @@ -218,659 +204,412 @@ void init_UE(int nb_inst) { * \param arg is a pointer to a \ref PHY_VARS_UE structure. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void *UE_thread_synch(void *arg) -{ - static int UE_thread_synch_retval; - int i, hw_slot_offset; - PHY_VARS_UE *UE = (PHY_VARS_UE*) arg; - int current_band = 0; - int current_offset = 0; - sync_mode_t sync_mode = pbch; - int CC_id = UE->CC_id; - int ind; - int found; - int freq_offset=0; - - UE->is_synchronized = 0; - printf("UE_thread_sync in with PHY_vars_UE %p\n",arg); - printf("waiting for sync (UE_thread_synch) \n"); - -#ifndef DEADLINE_SCHEDULER - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ - CPU_ZERO(&cpuset); - - #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } - #endif - - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity, 0 , sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf(temp, " CPU_%d ", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - - } - - LOG_I( HW, "[SCHED][UE] Started UE synch thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - (int) sparam.sched_priority, cpu_affinity); - -#endif - - - - - printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch); - ind = 0; - found = 0; - - - if (UE->UE_scan == 0) { - do { - current_band = eutra_bands[ind].band; - printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min); - - if ((eutra_bands[ind].dl_min <= downlink_frequency[0][0]) && (eutra_bands[ind].dl_max >= downlink_frequency[0][0])) { - for (i=0; i<4; i++) - uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; - - found = 1; - break; - } - - ind++; - } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0])); - - if (found == 0) { - exit_fun("Can't find EUTRA band for frequency"); - return &UE_thread_synch_retval; - } - - - - - - - LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],oai_exit, openair0_cfg[0].rx_num_channels); - - for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - if (uplink_frequency_offset[CC_id][i] != 0) // - openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; - else //FDD - openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; - } - - sync_mode = pbch; - - } else if (UE->UE_scan == 1) { - current_band=0; +static void *UE_thread_synch(void *arg) { + static int __thread UE_thread_synch_retval; + int i, hw_slot_offset; + PHY_VARS_UE *UE = (PHY_VARS_UE*) arg; + int current_band = 0; + int current_offset = 0; + sync_mode_t sync_mode = pbch; + int CC_id = UE->CC_id; + int freq_offset=0; + char threadname[128]; + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if ( threads.iq != -1 ) + CPU_SET(threads.iq, &cpuset); + // this thread priority must be lower that the main acquisition thread + sprintf(threadname, "sync UE %d\n", UE->Mod_id); + init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname); + + UE->is_synchronized = 0; + + if (UE->UE_scan == 0) { + int ind; + for ( ind=0; + ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]); + ind++) { + current_band = eutra_bands[ind].band; + LOG_D(PHY, "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min); + if ( eutra_bands[ind].dl_min <= downlink_frequency[0][0] && eutra_bands[ind].dl_max >= downlink_frequency[0][0] ) { + for (i=0; i<4; i++) + uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; + break; + } + } + AssertFatal( ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]), "Can't find EUTRA band for frequency"); + + LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", + downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0], + oai_exit, openair0_cfg[0].rx_num_channels); + + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + if (uplink_frequency_offset[CC_id][i] != 0) // + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; + else //FDD + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; + } + sync_mode = pbch; - for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { - downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; - - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + } else { + current_band=0; + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = + bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + } } - } - - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_sync_thread)\n"); + // AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); + while (oai_exit==0) { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + while (UE->proc.instance_cnt_synch < 0) + // the thread waits here most of the time + pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch ); + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - pthread_mutex_unlock(&sync_mutex); - printf("Started device, unlocked sync_mutex (UE_sync_thread)\n"); - - if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { - LOG_E(HW,"Could not start the device\n"); - oai_exit=1; - } - - while (oai_exit==0) { - - if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" ); - exit_fun("noting to add"); - return &UE_thread_synch_retval; - } - + switch (sync_mode) { + case pss: + LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + current_offset += 20000000; // increase by 20 MHz - while (UE->proc.instance_cnt_synch < 0) { - // the thread waits here most of the time - pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch ); - } - - if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_synch_retval; - } + if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) { + current_band++; + current_offset=0; + } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 1 ); + if (current_band==bands_to_scan.nbands) { + current_band=0; + oai_exit=1; + } - switch (sync_mode) { - case pss: - LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); - lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); - current_offset += 20000000; // increase by 20 MHz + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; - if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) { - current_band++; - current_offset=0; - } + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + if (UE->UE_scan_carrier) { + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } - if (current_band==bands_to_scan.nbands) { - current_band=0; - oai_exit=1; - } - - for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { - downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; - - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; - if (UE->UE_scan_carrier) { - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - } - - } - - break; - - case pbch: - - LOG_I(PHY,"[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); - if (initial_sync( UE, UE->mode ) == 0) { - - hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti; - LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", - hw_slot_offset, - freq_offset, - UE->rx_total_gain_dB, - downlink_frequency[0][0]+freq_offset, - downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset, - UE->UE_scan_carrier ); - - if (UE->UE_scan_carrier == 1) { - - UE->UE_scan_carrier = 0; - // rerun with new cell parameters and frequency-offset - for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) { - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - if (freq_offset >= 0) - { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += UE->common_vars.freq_offset; - } - else - { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= UE->common_vars.freq_offset; - } - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; - downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; - freq_offset=0; - } + } - // reconfigure for potentially different bandwidth - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; - openair0_cfg[UE->rf_map.card].rx_bw =.96e6; - openair0_cfg[UE->rf_map.card].tx_bw =.96e6; - // openair0_cfg[0].rx_gain[0] -= 12; - break; - case 25: - openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; - openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; - openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; - // openair0_cfg[0].rx_gain[0] -= 6; - break; - case 50: - openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; - openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; - openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; - // openair0_cfg[0].rx_gain[0] -= 3; - break; - case 100: - openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; - openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; - openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; - // openair0_cfg[0].rx_gain[0] -= 0; - break; - } - - UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); - //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); - UE->rfdevice.trx_stop_func(&UE->rfdevice); - sleep(1); - init_frame_parms(&UE->frame_parms,1); - if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { - LOG_E(HW,"Could not start the device\n"); - oai_exit=1; + break; + + case pbch: + + LOG_I(PHY,"[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); + if (initial_sync( UE, UE->mode ) == 0) { + + hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti; + LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", + hw_slot_offset, + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset, + UE->UE_scan_carrier ); + + + // rerun with new cell parameters and frequency-offset + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + if (UE->UE_scan_carrier == 1) { + if (freq_offset >= 0) + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset); + else + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; + downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; + freq_offset=0; + } } - } - else { - UE->is_synchronized = 1; - - if( UE->mode == rx_dump_frame ){ - FILE *fd; - if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) { // this guarantees SIB1 is present - if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { - fwrite((void*)&UE->common_vars.rxdata[0][0], - sizeof(int32_t), - 10*UE->frame_parms.samples_per_tti, - fd); - LOG_I(PHY,"Dummping Frame ... bye bye \n"); - fclose(fd); - exit(0); - } - else { - LOG_E(PHY,"Cannot open file for writing\n"); - exit(0); - } - } - else { - UE->is_synchronized = 0; - } - } - } - } else { - // initial sync failed - // calculate new offset and try again - if (UE->UE_scan_carrier == 1) { - if (freq_offset >= 0) { - freq_offset += 100; - freq_offset *= -1; - } else { - freq_offset *= -1; - } - - if (abs(freq_offset) > 7500) { - LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" ); - FILE *fd; - if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) { - fwrite((void*)&UE->common_vars.rxdata[0][0], - sizeof(int32_t), - 10*UE->frame_parms.samples_per_tti, - fd); - LOG_I(PHY,"Dummping Frame ... bye bye \n"); - fclose(fd); - exit(0); - } - mac_xface->macphy_exit("No cell synchronization found, abandoning"); - return &UE_thread_synch_retval; // not reached - } - } - else { - - } - LOG_I( PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", - freq_offset, - UE->rx_total_gain_dB, - downlink_frequency[0][0]+freq_offset, - downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); - - for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset; - - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - - if (UE->UE_scan_carrier==1) { - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - } - } - - UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); - - }// initial_sync=0 - break; - - case si: - default: - break; - } - - - if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE synch\n" ); - exit_fun("noting to add"); - return &UE_thread_synch_retval; - } - - // indicate readiness - UE->proc.instance_cnt_synch--; + // reconfigure for potentially different bandwidth + switch(UE->frame_parms.N_RB_DL) { + case 6: + openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; + openair0_cfg[UE->rf_map.card].rx_bw =.96e6; + openair0_cfg[UE->rf_map.card].tx_bw =.96e6; + // openair0_cfg[0].rx_gain[0] -= 12; + break; + case 25: + openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; + openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; + openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; + // openair0_cfg[0].rx_gain[0] -= 6; + break; + case 50: + openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; + openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; + openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; + // openair0_cfg[0].rx_gain[0] -= 3; + break; + case 100: + openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; + openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; + openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; + // openair0_cfg[0].rx_gain[0] -= 0; + break; + } + + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); + //UE->rfdevice.trx_stop_func(&UE->rfdevice); + sleep(1); + init_frame_parms(&UE->frame_parms,1); + /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + }*/ + + if (UE->UE_scan_carrier == 1) { + + UE->UE_scan_carrier = 0; + } else { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + UE->is_synchronized = 1; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + + if( UE->mode == rx_dump_frame ) { + FILE *fd; + if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) { // this guarantees SIB1 is present + if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { + fwrite((void*)&UE->common_vars.rxdata[0][0], + sizeof(int32_t), + 10*UE->frame_parms.samples_per_tti, + fd); + LOG_I(PHY,"Dummping Frame ... bye bye \n"); + fclose(fd); + exit(0); + } else { + LOG_E(PHY,"Cannot open file for writing\n"); + exit(0); + } + } else { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + UE->is_synchronized = 0; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + + } + } + } + } else { + // initial sync failed + // calculate new offset and try again + if (UE->UE_scan_carrier == 1) { + if (freq_offset >= 0) + freq_offset += 100; + freq_offset *= -1; + + if (abs(freq_offset) > 7500) { + LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" ); + FILE *fd; + if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) { + fwrite((void*)&UE->common_vars.rxdata[0][0], + sizeof(int32_t), + 10*UE->frame_parms.samples_per_tti, + fd); + LOG_I(PHY,"Dummping Frame ... bye bye \n"); + fclose(fd); + exit(0); + } + mac_xface->macphy_exit("No cell synchronization found, abandoning"); + return &UE_thread_synch_retval; // not reached + } + } + LOG_I( PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); + + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + if (UE->UE_scan_carrier==1) + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + }// initial_sync=0 + break; + case si: + default: + break; + } - if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE synch\n" ); - exit_fun("noting to add"); - return &UE_thread_synch_retval; - } + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + // indicate readiness + UE->proc.instance_cnt_synch--; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 ); - } // while !oai_exit + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 ); + } // while !oai_exit - return &UE_thread_synch_retval; + return &UE_thread_synch_retval; } +/* this structure is used to pass both UE phy vars and + * proc to the function UE_thread_rxn_txnp4 + */ +struct rx_tx_thread_data { + PHY_VARS_UE *UE; + UE_rxtx_proc_t *proc; +}; /*! * \brief This is the UE thread for RX subframe n and TX subframe n+4. * This thread performs the phy_procedures_UE_RX() on every received slot. - * then, if TX is enabled it performs TX for n+4. + * then, if TX is enabled it performs TX for n+4. * \param arg is a pointer to a \ref PHY_VARS_UE structure. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void *UE_thread_rxn_txnp4(void *arg) -{ - static int UE_thread_rxtx_retval; - UE_rxtx_proc_t *proc = (UE_rxtx_proc_t *)arg; - int ret; - PHY_VARS_UE *UE=PHY_vars_UE_g[0][proc->CC_id]; - proc->instance_cnt_rxtx=-1; - - -#ifdef DEADLINE_SCHEDULER - - struct sched_attr attr; - unsigned int flags = 0; - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - // This creates a .5ms reservation every 1ms period - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = 900000; // each rx thread requires 1ms to finish its job - attr.sched_deadline = 1000000; // each rx thread will finish within 1ms - attr.sched_period = 1000000; // each rx thread has a period of 1ms from the starting point - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] UE_thread_rxtx : sched_setattr failed\n"); - return &UE_thread_rxtx_retval; - } - -#else - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ - CPU_ZERO(&cpuset); - - #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } - #endif - - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity, 0 , sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf(temp, " CPU_%d ", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - - } - - LOG_I( HW, "[SCHED][UE] Started UE RX thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - (int) sparam.sched_priority, cpu_affinity); - - -#endif - - // Lock memory from swapping. This is a process wide call (not constraint to this thread). - mlockall(MCL_CURRENT | MCL_FUTURE); - - printf("waiting for sync (UE_thread_rxn_txnp4)\n"); - - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_thread_rxn_txnp4)\n"); - - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - -#define THREAD_NAME_LEN 16 - char threadname[THREAD_NAME_LEN]; - ret = pthread_getname_np(proc->pthread_rxtx, threadname, THREAD_NAME_LEN); - if (ret != 0) - { - perror("pthread_getname_np : "); - exit_fun("Error getting thread name"); - } - - pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex, waiting (UE_thread_rxtx)\n"); +static void *UE_thread_rxn_txnp4(void *arg) { + static __thread int UE_thread_rxtx_retval; + struct rx_tx_thread_data *rtd = arg; + UE_rxtx_proc_t *proc = rtd->proc; + PHY_VARS_UE *UE = rtd->UE; + int ret; + + proc->instance_cnt_rxtx=-1; + proc->subframe_rx=proc->sub_frame_start; + + char threadname[256]; + sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if ( (proc->sub_frame_start+1)%2 == 0 && threads.even != -1 ) + CPU_SET(threads.even, &cpuset); + if ( (proc->sub_frame_start+1)%2 == 1 && threads.odd != -1 ) + CPU_SET(threads.odd, &cpuset); + init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, + threadname); + + while (!oai_exit) { + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); + exit_fun("nothing to add"); + } + while (proc->instance_cnt_rxtx < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); + } + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); + exit_fun("nothing to add"); + } - printf("Starting UE RXN_TXNP4 thread (%s)\n", threadname); + initRefTimes(t2); + initRefTimes(t3); + pickTime(current); + updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)"); + + // Process Rx data for one sub-frame + lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx); + if ((sf_type == SF_DL) || + (UE->frame_parms.frame_type == FDD) || + (sf_type == SF_S)) { + + if (UE->frame_parms.frame_type == TDD) { + LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n", + threadname, + UE->frame_parms.tdd_config, + (sf_type==SF_DL? "SF_DL" : + (sf_type==SF_UL? "SF_UL" : + (sf_type==SF_S ? "SF_S" : "UNKNOWN_SF_TYPE")))); + } else { + LOG_D(PHY, "%s,%s,%s: calling UE_RX\n", + threadname, + (UE->frame_parms.frame_type==FDD? "FDD": + (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")), + (sf_type==SF_DL? "SF_DL" : + (sf_type==SF_UL? "SF_UL" : + (sf_type==SF_S ? "SF_S" : "UNKNOWN_SF_TYPE")))); + } + phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL ); + } - while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0+(proc->proc_id), 1 ); - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); - exit_fun("nothing to add"); - return &UE_thread_rxtx_retval; - } + start_meas(&UE->generic_stat); + + if (UE->mac_enabled==1) { + + ret = mac_xface->ue_scheduler(UE->Mod_id, + proc->frame_rx, + proc->subframe_rx, + proc->frame_tx, + proc->subframe_tx, + subframe_select(&UE->frame_parms,proc->subframe_tx), + 0, + 0/*FIXME CC_id*/); + if ( ret != CONNECTION_OK) { + char *txt; + switch (ret) { + case CONNECTION_LOST: + txt="RRC Connection lost, returning to PRACH"; + break; + case PHY_RESYNCH: + txt="RRC Connection lost, trying to resynch"; + break; + case RESYNCH: + txt="return to PRACH and perform a contention-free access"; + break; + default: + txt="UNKNOWN RETURN CODE"; + }; + LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n", + UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt ); + } + } - while (proc->instance_cnt_rxtx < 0) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0+(proc->proc_id), 1 ); - // most of the time, the thread is waiting here - pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0+(proc->proc_id), 0 ); + stop_meas(&UE->generic_stat); - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); - exit_fun("nothing to add"); - return &UE_thread_rxtx_retval; - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0+(proc->proc_id), 0 ); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->proc_id), 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE+(proc->proc_id), proc->subframe_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_UE+(proc->proc_id), proc->subframe_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE+(proc->proc_id), proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE+(proc->proc_id), proc->frame_tx ); - - lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx); - if ((sf_type == SF_DL) || - (UE->frame_parms.frame_type == FDD) || - (sf_type == SF_S)) { - - if (UE->frame_parms.frame_type == TDD) { - LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n", - threadname, - UE->frame_parms.tdd_config, - (sf_type==SF_DL? "SF_DL" : - (sf_type==SF_UL? "SF_UL" : - (sf_type==SF_S ? "SF_S" : "UNKNOWN_SF_TYPE")))); - } else { - LOG_D(PHY, "%s,%s,%s: calling UE_RX\n", - threadname, - (UE->frame_parms.frame_type==FDD? "FDD": - (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")), - (sf_type==SF_DL? "SF_DL" : - (sf_type==SF_UL? "SF_UL" : - (sf_type==SF_S ? "SF_S" : "UNKNOWN_SF_TYPE")))); - } - phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL ); - } - - if (UE->mac_enabled==1) { - - ret = mac_xface->ue_scheduler(UE->Mod_id, - proc->frame_rx, - proc->subframe_rx, - proc->frame_tx, - proc->subframe_tx, - subframe_select(&UE->frame_parms,proc->subframe_tx), - 0, - 0/*FIXME CC_id*/); - - if (ret == CONNECTION_LOST) { - LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, returning to PRACH\n", - UE->Mod_id, proc->frame_rx, proc->subframe_tx ); - UE->UE_mode[0] = PRACH; - } else if (ret == PHY_RESYNCH) { - LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, trying to resynch\n", - UE->Mod_id, proc->frame_rx, proc->subframe_tx ); - UE->UE_mode[0] = RESYNCH; - } else if (ret == PHY_HO_PRACH) { - LOG_I( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u, return to PRACH and perform a contention-free access\n", - UE->Mod_id, proc->frame_rx, proc->subframe_tx ); - UE->UE_mode[0] = PRACH; - } - } + // Prepare the future Tx data - if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || - (UE->frame_parms.frame_type == FDD) ) { + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || + (UE->frame_parms.frame_type == FDD) ) + if (UE->mode != loop_through_memory) + phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay); - if (UE->mode != loop_through_memory) { - phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay); - } - } - if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) && - (UE->frame_parms.frame_type == TDD)) { + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) && + (UE->frame_parms.frame_type == TDD)) + if (UE->mode != loop_through_memory) + phy_procedures_UE_S_TX(UE,0,0,no_relay); + updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)"); - if (UE->mode != loop_through_memory) { - phy_procedures_UE_S_TX(UE,0,0,no_relay); - } + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); + exit_fun("noting to add"); + } + proc->instance_cnt_rxtx--; + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" ); + exit_fun("noting to add"); + } } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->proc_id), 0 ); - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0+(proc->proc_id), 1 ); - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); - exit_fun("noting to add"); - return &UE_thread_rxtx_retval; - } - - proc->instance_cnt_rxtx--; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, proc->instance_cnt_rxtx); - - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" ); - exit_fun("noting to add"); - return &UE_thread_rxtx_retval; - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0+(proc->proc_id), 0 ); - } - - // thread finished - return &UE_thread_rxtx_retval; +// thread finished + free(arg); + return &UE_thread_rxtx_retval; } - - - - -#define RX_OFF_MAX 23 -#define RX_OFF_MIN 0 -#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2) - /*! * \brief This is the main UE thread. * This thread controls the other three UE threads: @@ -883,805 +622,222 @@ static void *UE_thread_rxn_txnp4(void *arg) void *UE_thread(void *arg) { - static int UE_thread_retval; - PHY_VARS_UE *UE = PHY_vars_UE_g[0][0]; - // int tx_enabled = 0; - uint32_t rxs=0,txs=0; - int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32))); - openair0_timestamp timestamp,timestamp1; - void* rxp[2], *txp[2]; - -#ifdef NAS_UE - MessageDef *message_p; -#endif - - int start_rx_stream = 0; - int rx_off_diff = 0; - int rx_correction_timer = 0; - int i; - -#ifdef DEADLINE_SCHEDULER - - struct sched_attr attr; - unsigned int flags = 0; - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0;//sched_get_priority_max(SCHED_DEADLINE); - - // This creates a .5 ms reservation - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = 100000; - attr.sched_deadline = 500000; - attr.sched_period = 500000; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] main eNB thread: sched_setattr failed\n"); - exit_fun("Nothing to add"); - return &UE_thread_retval; - } - LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %lu started on CPU %d\n", - (unsigned long)gettid(), sched_getcpu()); - -#else - struct sched_param sp; - sp.sched_priority = sched_get_priority_max(SCHED_FIFO); - pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); -#endif - - // Lock memory from swapping. This is a process wide call (not constraint to this thread). - mlockall(MCL_CURRENT | MCL_FUTURE); - - printf("waiting for sync (UE_thread)\n"); - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_thread)\n"); - - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - - pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex, waiting (UE_thread)\n"); - - printf("starting UE thread\n"); - -#ifdef NAS_UE - message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); - itti_send_msg_to_task (TASK_NAS_UE, INSTANCE_DEFAULT, message_p); -#endif - - while (!oai_exit) { - - if (UE->is_synchronized == 0) { - - if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] verror locking mutex for UE initial synch thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - int instance_cnt_synch = UE->proc.instance_cnt_synch; - - if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE initial synch thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - if (instance_cnt_synch < 0) { // we can invoke the synch - // grab 10 ms of signal and wakeup synch thread - for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&UE->common_vars.rxdata[i][0]; - - if (UE->mode != loop_through_memory) { - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti*10, - UE->frame_parms.nb_antennas_rx); - - - if (rxs!=UE->frame_parms.samples_per_tti*10) { - LOG_E(PHY, "problem in rx 1! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti*10, rxs); - exit_fun("problem in rx 1"); - return &UE_thread_retval; - } - } - - instance_cnt_synch = ++UE->proc.instance_cnt_synch; - if (instance_cnt_synch == 0) { - if (pthread_cond_signal(&UE->proc.cond_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - } else { - LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - } // - else { - // grab 10 ms of signal into dummy buffer - - if (UE->mode != loop_through_memory) { - for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&dummy_rx[i][0]; - for (int sf=0;sf<10;sf++) { - // printf("Reading dummy sf %d\n",sf); - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti, - UE->frame_parms.nb_antennas_rx); - - if (rxs!=UE->frame_parms.samples_per_tti){ - LOG_E(PHY, "problem in rx 2! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti, rxs); - exit_fun("problem in rx 2"); - return &UE_thread_retval; - } - - } - } - } - - } // UE->is_synchronized==0 - else { - if (start_rx_stream==0) { - start_rx_stream=1; - if (UE->mode != loop_through_memory) { - - if (UE->no_timing_correction==0) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)UE->common_vars.rxdata, - UE->rx_offset, - UE->frame_parms.nb_antennas_rx); - if (rxs != UE->rx_offset) { - LOG_E(PHY, "problem in rx 3! expect #samples=%d but got only %d!\n", UE->rx_offset, rxs); - exit_fun("problem in rx 3!"); - return &UE_thread_retval; - } - } - LOG_D(PHY,"Set rx_offset to 0 \n"); - UE->rx_offset=0; - UE->proc.proc_rxtx[0].frame_rx++; - UE->proc.proc_rxtx[1].frame_rx++; - - // read in first symbol - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)UE->common_vars.rxdata, - UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, - UE->frame_parms.nb_antennas_rx); - if (rxs != (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0)) { - LOG_E(PHY, "problem in rx 4! expect #samples=%d but got only %d!\n", UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, rxs); - exit_fun("problem in rx 4!"); - return &UE_thread_retval; - } - slot_fep(UE, - 0, - 0, - 0, - 0, - 0); - if (rxs != UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0) { - exit_fun("problem in rx"); - return &UE_thread_retval; - } - } //UE->mode != loop_through_memory - else - rt_sleep_ns(1000000); - - }// start_rx_stream==0 - else { - //UE->proc.proc_rxtx[0].frame_rx++; - //UE->proc.proc_rxtx[1].frame_rx++; - - for (int sf=0;sf<10;sf++) { - for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti)]; - // grab signal for subframe - if (UE->mode != loop_through_memory) { - if (sf<9) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti, - UE->frame_parms.nb_antennas_rx); - LOG_D(PHY,"grab signal for subframe %d offset %d Nbsamples %d \n", sf, UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti), - UE->frame_parms.samples_per_tti); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS_MISSING, UE->frame_parms.samples_per_tti - rxs); - if (rxs != UE->frame_parms.samples_per_tti) { - LOG_E(PHY, "problem in rx 5! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti, rxs); - exit_fun("problem in rx 5!"); - return &UE_thread_retval; - } - - // prepare tx buffer pointers - for (i=0; i<UE->frame_parms.nb_antennas_tx; i++) - txp[i] = (void*)&UE->common_vars.txdata[i][((sf+2)%10)*UE->frame_parms.samples_per_tti]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - txs = UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - (2*UE->frame_parms.samples_per_tti) - - UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - - openair0_cfg[0].tx_sample_advance, - txp, - UE->frame_parms.samples_per_tti, - UE->frame_parms.nb_antennas_tx, - 1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS, txs ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS_MISSING, UE->frame_parms.samples_per_tti - txs); - if (txs != UE->frame_parms.samples_per_tti) { - LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti); - exit_fun( "problem transmitting samples" ); - } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS_MISSING, UE->frame_parms.samples_per_tti - txs); - } - - else { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 1 ); - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0, - UE->frame_parms.nb_antennas_rx); - - LOG_D(PHY,"grab signal for subframe %d offset %d Nbsamples %d \n", sf, UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti), - UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS_MISSING, (UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0) - rxs); - if (rxs != (UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0)) { - LOG_E(PHY, "problem in rx 6! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0, rxs); - exit_fun("problem in rx 6!"); - return &UE_thread_retval; - } - - // prepare tx buffer pointers - for (i=0; i<UE->frame_parms.nb_antennas_tx; i++) - txp[i] = (void*)&UE->common_vars.txdata[i][((sf+2)%10)*UE->frame_parms.samples_per_tti]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_SF9, 1 ); - txs = UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - (2*UE->frame_parms.samples_per_tti) - - UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - - openair0_cfg[0].tx_sample_advance, - txp, - UE->frame_parms.samples_per_tti - rx_off_diff, - UE->frame_parms.nb_antennas_tx, - 1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_SF9, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS, txs ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS_MISSING, (UE->frame_parms.samples_per_tti - rx_off_diff) - txs); - if (txs != UE->frame_parms.samples_per_tti - rx_off_diff) { - LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti-rx_off_diff); - exit_fun( "problem transmitting samples" ); - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 1 ); - // read in first symbol of next frame and adjust for timing drift - for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) - { - rxp[i] = (void*)&UE->common_vars.rxdata[i][0]; - } - - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp1, - rxp, - UE->frame_parms.nb_prefix_samples0 - rx_off_diff, - UE->frame_parms.nb_antennas_rx); - - for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) - { - rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.nb_prefix_samples0]; - } - - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp1, - rxp, - UE->frame_parms.ofdm_symbol_size, - UE->frame_parms.nb_antennas_rx); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs ); - if (rxs != (UE->frame_parms.ofdm_symbol_size)) { - LOG_E(PHY, "problem in rx 7! expect #samples=%d but got only %d! rx_off_diff=%d\n", UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff, rxs, rx_off_diff); - exit_fun("problem in rx 7!"); - return &UE_thread_retval; - } - UE->rx_offset_diff = rx_off_diff; - LOG_D(PHY,"SET rx_off_diff to %d\n",UE->rx_offset_diff); - rx_off_diff = 0; - } - } - // operate on thread sf mod 2 - uint8_t proc_select = sf&1; - UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[proc_select]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0+proc_select, 1 ); - // lock mutex - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - // increment instance count and change proc subframe/frame variables - int instance_cnt_rxtx = ++proc->instance_cnt_rxtx; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, proc->instance_cnt_rxtx); - if(sf == 0) - { - UE->proc.proc_rxtx[0].frame_rx++; - UE->proc.proc_rxtx[1].frame_rx++; - } - proc->subframe_rx=sf; - proc->subframe_tx=(sf+4)%10; - proc->frame_tx = proc->frame_rx + ((proc->subframe_rx>5)?1:0); - proc->timestamp_tx = timestamp+(4*UE->frame_parms.samples_per_tti)-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; - -#if T_TRACER - T(T_UE_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx%1024), T_INT(proc->subframe_rx)); -#endif - /* - if (sf != (timestamp/UE->frame_parms.samples_per_tti)%10) { - LOG_E(PHY,"steady-state UE_thread error : frame_rx %d, subframe_rx %d, frame_tx %d, subframe_tx %d, rx subframe %d\n",proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,(timestamp/UE->frame_parms.samples_per_tti)%10); - exit(-1); - } - */ - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0+proc_select, 0 ); - - - if (instance_cnt_rxtx == 0) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX0+proc_select, 1 ); - if (pthread_cond_signal(&proc->cond_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - LOG_D(PHY, "firing up rxtx_thread[%d] at subframe %d\n", proc_select, sf); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX0+proc_select, 0 ); - - } else { - LOG_E( PHY, "[SCHED][UE] UE RX thread busy (IC %d)!!\n", instance_cnt_rxtx); - if (instance_cnt_rxtx > 2) { - sleep(1); - exit_fun("instance_cnt_rxtx > 2"); - return &UE_thread_retval; - } - } - if (UE->mode == loop_through_memory) { - printf("Processing subframe %d",proc->subframe_rx); - getchar(); - } - }// for sf=0..10 - - uint8_t proc_select = 9&1; - UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[proc_select]; - - if (UE->no_timing_correction == 0) { - if ((UE->rx_offset<(5*UE->frame_parms.samples_per_tti)) && - (UE->rx_offset > 0) && - (rx_correction_timer == 0)) { - rx_off_diff = -1 ; - LOG_D(PHY,"AbsSubframe %d.%d UE->rx_offset %d > %d, diff %d\n",proc->frame_rx,proc->subframe_rx,UE->rx_offset,0,rx_off_diff); - rx_correction_timer = 5; - } else if ((UE->rx_offset>(5*UE->frame_parms.samples_per_tti)) && - (UE->rx_offset < ((10*UE->frame_parms.samples_per_tti))) && - (rx_correction_timer == 0)) { // moving to the left so drop rx_off_diff samples - rx_off_diff = 1; - LOG_D(PHY,"AbsSubframe %d.%d UE->rx_offset %d < %d, diff %d\n",proc->frame_rx,proc->subframe_rx,UE->rx_offset,10*UE->frame_parms.samples_per_tti,rx_off_diff); - - rx_correction_timer = 5; - } - - if (rx_correction_timer>0) - rx_correction_timer--; - } - } // start_rx_stream==1 - } // UE->is_synchronized==1 - - } // while !oai_exit - return NULL; -} // UE_thread - -/* -void *UE_thread_old(void *arg) -{ - UNUSED(arg) - static int UE_thread_retval; - PHY_VARS_UE *UE = PHY_vars_UE_g[0][0]; - int spp = openair0_cfg[0].samples_per_packet; - int slot=1, frame=0, hw_subframe=0, rxpos=0, txpos=openair0_cfg[0].tx_scheduling_advance; -#ifdef __AVX2__ - int dummy[2][spp] __attribute__((aligned(32))); -#else - int dummy[2][spp] __attribute__((aligned(16))); -#endif - int dummy_dump = 0; - int tx_enabled = 0; - int start_rx_stream = 0; - int rx_off_diff = 0; - int rx_correction_timer = 0; - int first_rx = 0; - RTIME T0; - unsigned int rxs; - void* rxp[2]; - - openair0_timestamp timestamp; - -#ifdef NAS_UE - MessageDef *message_p; -#endif - -#ifdef DEADLINE_SCHEDULER - - struct sched_attr attr; - unsigned int flags = 0; - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0;//sched_get_priority_max(SCHED_DEADLINE); - - // This creates a .5 ms reservation - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = 100000; - attr.sched_deadline = 500000; - attr.sched_period = 500000; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] main eNB thread: sched_setattr failed\n"); - exit_fun("Nothing to add"); - return &UE_thread_retval; - } - LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %lu started on CPU %d\n", - (unsigned long)gettid(), sched_getcpu()); - -#else - struct sched_param sp; - sp.sched_priority = sched_get_priority_max(SCHED_FIFO); - pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); -#endif - - // Lock memory from swapping. This is a process wide call (not constraint to this thread). - mlockall(MCL_CURRENT | MCL_FUTURE); - - printf("waiting for sync (UE_thread)\n"); - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_thread)\n"); - - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - - pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex, waiting (UE_thread)\n"); - - printf("starting UE thread\n"); + PHY_VARS_UE *UE = (PHY_VARS_UE *) arg; + // int tx_enabled = 0; + int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32))); + openair0_timestamp timestamp,timestamp1; + void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX]; + int start_rx_stream = 0; + int i; + char threadname[128]; + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if ( threads.iq != -1 ) + CPU_SET(threads.iq, &cpuset); + init_thread(100000, 500000, FIFO_PRIORITY, &cpuset, + "UHD Threads"); + if (oaisim_flag == 0) + AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); + UE->rfdevice.host_type = BBU_HOST; + sprintf(threadname, "Main UE %d", UE->Mod_id); + pthread_setname_np(pthread_self(), threadname); + init_UE_threads(UE); #ifdef NAS_UE - message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); - itti_send_msg_to_task (TASK_NAS_UE, INSTANCE_DEFAULT, message_p); -#endif - - T0 = rt_get_time_ns(); - first_rx = 1; - rxpos=0; - - while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP, dummy_dump ); - - - while (rxpos < (1+hw_subframe)*UE->frame_parms.samples_per_tti) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - -#ifndef USRP_DEBUG - - DevAssert( UE->frame_parms.nb_antennas_rx <= 2 ); - void* rxp[2]; - - for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) - rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rxpos] : (void*)dummy[i]; - - - if (UE->mode != loop_through_memory) { - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - spp - ((first_rx==1) ? rx_off_diff : 0), - UE->frame_parms.nb_antennas_rx); - - if (rxs != (spp- ((first_rx==1) ? rx_off_diff : 0))) { - printf("rx error: asked %d got %d ",spp - ((first_rx==1) ? rx_off_diff : 0),rxs); - if (UE->is_synchronized == 1) { - exit_fun("problem in rx"); - return &UE_thread_retval; - } - } - } - - if (rx_off_diff !=0) - LOG_D(PHY,"frame %d, rx_offset %d, rx_off_diff %d\n",UE->frame_rx,UE->rx_offset,rx_off_diff); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - - // Transmit TX buffer based on timestamp from RX - if ((tx_enabled==1) && (UE->mode!=loop_through_memory)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - - DevAssert( UE->frame_parms.nb_antennas_tx <= 2 ); - void* txp[2]; - - for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) - txp[i] = (void*)&txdata[i][txpos]; - - UE->rfdevice.trx_write_func(&openair0, - (timestamp+openair0_cfg[0].tx_scheduling_advance-openair0_cfg[0].tx_sample_advance), - txp, - spp - ((first_rx==1) ? rx_off_diff : 0), - UE->frame_parms.nb_antennas_tx, - 1); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - } - else if (UE->mode == loop_through_memory) - rt_sleep_ns(1000000); -#else - // define USRP_DEBUG is active - rt_sleep_ns(1000000); + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); + itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p); #endif - rx_off_diff = 0; - first_rx = 0; - - rxpos += spp; - txpos += spp; - - if (txpos >= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti) - txpos -= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti; - } - - if (rxpos >= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti) - rxpos -= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti; - - if (UE->is_synchronized == 1) { - LOG_D( HW, "UE_thread: hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 ); - - if (start_rx_stream == 1) { - LOG_D(PHY,"Locking mutex_rx (IC %d)\n",UE->instance_cnt_rx); - if (pthread_mutex_lock(&UE->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - int instance_cnt_rx = ++UE->instance_cnt_rx; - - LOG_D(PHY,"Unlocking mutex_rx (IC %d)\n",instance_cnt_rx); - if (pthread_mutex_unlock(&UE->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, instance_cnt_rx); - - - if (instance_cnt_rx == 0) { - LOG_D(HW,"signalling rx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 ); - if (pthread_cond_signal(&UE->proc.cond_rx) != 0) { - LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - LOG_D(HW,"signalled rx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 ); - if (UE->mode == loop_through_memory) { - printf("Processing subframe %d",UE->slot_rx>>1); - getchar(); - } - - if (UE->mode == rx_calib_ue) { - if (frame == 10) { - LOG_D(PHY, - "[SCHED][UE] Found cell with N_RB_DL %"PRIu8", PHICH CONFIG (%d,%d), Nid_cell %"PRIu16", NB_ANTENNAS_TX %"PRIu8", frequency offset "PRIi32" Hz, RSSI (digital) %hu dB, measured Gain %d dB, total_rx_gain %"PRIu32" dB, USRP rx gain %f dB\n", - UE->frame_parms.N_RB_DL, - UE->frame_parms.phich_config_common.phich_duration, - UE->frame_parms.phich_config_common.phich_resource, - UE->frame_parms.Nid_cell, - UE->frame_parms.nb_antennas_tx_eNB, - UE->common_vars.freq_offset, - UE->measurements.rx_power_avg_dB[0], - UE->measurements.rx_power_avg_dB[0] - rx_input_level_dBm, - UE->rx_total_gain_dB, - openair0_cfg[0].rx_gain[0] - ); - exit_fun("[HW][UE] UE in RX calibration mode, exiting"); - return &UE_thread_retval; - } - } - } else { - LOG_E( PHY, "[SCHED][UE] UE RX thread busy (IC %d)!!\n", instance_cnt_rx); - if (instance_cnt_rx > 2) { - exit_fun("instance_cnt_rx > 1"); - return &UE_thread_retval; - } - } - - - if ((tx_enabled==1)&&(UE->mode != loop_through_memory)) { - - if (pthread_mutex_lock(&UE->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE TX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - - int instance_cnt_tx = ++UE->instance_cnt_tx; - - if (pthread_mutex_unlock(&UE->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE TX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX, instance_cnt_tx); - - - if (instance_cnt_tx == 0) { - if (pthread_cond_signal(&UE->cond_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE TX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; + int sub_frame=-1; + //int cumulated_shift=0; + AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); + while (!oai_exit) { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + int instance_cnt_synch = UE->proc.instance_cnt_synch; + int is_synchronized = UE->is_synchronized; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + + if (is_synchronized == 0) { + if (instance_cnt_synch < 0) { // we can invoke the synch + // grab 10 ms of signal and wakeup synch thread + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&UE->common_vars.rxdata[i][0]; + + if (UE->mode != loop_through_memory) + AssertFatal( UE->frame_parms.samples_per_tti*10 == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti*10, + UE->frame_parms.nb_antennas_rx), ""); + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + instance_cnt_synch = ++UE->proc.instance_cnt_synch; + if (instance_cnt_synch == 0) { + AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), ""); + } else { + LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" ); + exit_fun("nothing to add"); + } + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + } else { + // grab 10 ms of signal into dummy buffer + if (UE->mode != loop_through_memory) { + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&dummy_rx[i][0]; + for (int sf=0; sf<10; sf++) + // printf("Reading dummy sf %d\n",sf); + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx); + } } - LOG_D(HW,"signalled tx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 ); - - } else { - LOG_E( PHY, "[SCHED][UE] UE TX thread busy (IC %d)!!\n" ); - if (instance_cnt_tx>2) { - exit_fun("instance_cnt_tx > 1"); - return &UE_thread_retval; - } - } - } - - } - } else { - // we are not yet synchronized - if ((hw_subframe == 9) && (dummy_dump == 0)) { - // Wake up initial synch thread - if (pthread_mutex_lock(&UE->mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - - int instance_cnt_synch = ++UE->instance_cnt_synch; - - if (pthread_mutex_unlock(&UE->mutex_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE initial synch thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - dummy_dump = 1; - - if (instance_cnt_synch == 0) { - if (pthread_cond_signal(&UE->cond_synch) != 0) { - LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - } else { - LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" ); - exit_fun("nothing to add"); - return &UE_thread_retval; - } - } - } - - hw_subframe++; - slot+=2; - - if (hw_subframe==10) { - hw_subframe = 0; - first_rx = 1; - frame++; - slot = 1; - - int fail = pthread_mutex_lock(&UE->mutex_synch); - int instance_cnt_synch = UE->instance_cnt_synch; - fail = fail || pthread_mutex_unlock(&UE->mutex_synch); - - if (fail) { - LOG_E( PHY, "[SCHED][UE] error (un-)locking mutex for UE synch\n" ); - exit_fun("noting to add"); - return &UE_thread_retval; - } - - if (instance_cnt_synch < 0) { - // the UE_thread_synch is ready - if (UE->is_synchronized == 1) { - rx_off_diff = 0; - LTE_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; // for macro FRAME_LENGTH_COMPLEX_SAMPLES - - // LOG_I(PHY,"UE->rx_offset %d\n",UE->rx_offset); - if ((UE->rx_offset > RX_OFF_MAX) && (start_rx_stream == 0)) { - start_rx_stream=1; - frame=0; - // dump ahead in time to start of frame - -#ifndef USRP_DEBUG - if (UE->mode != loop_through_memory) { - LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)rxdata, - UE->rx_offset, - UE->frame_parms.nb_antennas_rx); - if (rxs != UE->rx_offset) { - exit_fun("problem in rx"); - return &UE_thread_retval; - } - UE->rx_offset=0; - tx_enabled = 1; - } - else - rt_sleep_ns(1000000); -#else - rt_sleep_ns(10000000); -#endif - - } else if ((UE->rx_offset<(FRAME_LENGTH_COMPLEX_SAMPLES/2)) && - (UE->rx_offset > RX_OFF_MIN) && - (start_rx_stream==1) && - (rx_correction_timer == 0)) { - rx_off_diff = -UE->rx_offset + RX_OFF_MIN; - LOG_D(PHY,"UE->rx_offset %d > %d, diff %d\n",UE->rx_offset,RX_OFF_MIN,rx_off_diff); - rx_correction_timer = 5; - } else if ((UE->rx_offset>(FRAME_LENGTH_COMPLEX_SAMPLES/2)) && - (UE->rx_offset < (FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MIN)) && - (start_rx_stream==1) && - (rx_correction_timer == 0)) { // moving to the left so drop rx_off_diff samples - rx_off_diff = FRAME_LENGTH_COMPLEX_SAMPLES - RX_OFF_MIN - UE->rx_offset; - LOG_D(PHY,"UE->rx_offset %d < %d, diff %d\n",UE->rx_offset,FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MIN,rx_off_diff); - - rx_correction_timer = 5; - } - - if (rx_correction_timer>0) - rx_correction_timer--; - } - - dummy_dump=0; - } - } - -#if defined(ENABLE_ITTI) - itti_update_lte_time(frame, slot); -#endif - } - - return &UE_thread_retval; + } // UE->is_synchronized==0 + else { + if (start_rx_stream==0) { + start_rx_stream=1; + if (UE->mode != loop_through_memory) { + if (UE->no_timing_correction==0) { + LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + AssertFatal(UE->rx_offset == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void**)UE->common_vars.rxdata, + UE->rx_offset, + UE->frame_parms.nb_antennas_rx),""); + } + UE->rx_offset=0; + UE->proc.proc_rxtx[0].frame_rx++; + UE->proc.proc_rxtx[1].frame_rx++; + + // read in first symbol + AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void**)UE->common_vars.rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx),""); + slot_fep(UE,0, 0, 0, 0, 0); + } //UE->mode != loop_through_memory + else + rt_sleep_ns(1000*1000); + + } else { + sub_frame++; + sub_frame%=10; + UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[sub_frame&1]; + + if (UE->mode != loop_through_memory) { + for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+ + UE->frame_parms.nb_prefix_samples0+ + sub_frame*UE->frame_parms.samples_per_tti]; + for (i=0; i<UE->frame_parms.nb_antennas_tx; i++) + txp[i] = (void*)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_tti]; + + int readBlockSize, writeBlockSize; + if (sub_frame<9) { + readBlockSize=UE->frame_parms.samples_per_tti; + writeBlockSize=UE->frame_parms.samples_per_tti; + } else { + // set TO compensation to zero + UE->rx_offset_diff = 0; + // compute TO compensation that should be applied for this frame + if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti && + UE->rx_offset > 0 ) + UE->rx_offset_diff = -1 ; + if ( UE->rx_offset > 5*UE->frame_parms.samples_per_tti && + UE->rx_offset < 10*UE->frame_parms.samples_per_tti ) + UE->rx_offset_diff = 1; + + LOG_D(PHY,"AbsSubframe %d.%d SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,sub_frame,UE->rx_offset_diff,UE->rx_offset); + readBlockSize=UE->frame_parms.samples_per_tti - + UE->frame_parms.ofdm_symbol_size - + UE->frame_parms.nb_prefix_samples0 - + UE->rx_offset_diff; + writeBlockSize=UE->frame_parms.samples_per_tti - + UE->rx_offset_diff; + } + + AssertFatal(readBlockSize == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + readBlockSize, + UE->frame_parms.nb_antennas_rx),""); + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + (2*UE->frame_parms.samples_per_tti) - + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - + openair0_cfg[0].tx_sample_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 1),""); + if( sub_frame==9) { + // read in first symbol of next frame and adjust for timing drift + int first_symbols=writeBlockSize-readBlockSize; + if ( first_symbols > 0 ) + AssertFatal(first_symbols == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp1, + (void**)UE->common_vars.rxdata, + first_symbols, + UE->frame_parms.nb_antennas_rx),""); + if ( first_symbols <0 ) + LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); + } + pickTime(gotIQs); + // operate on thread sf mod 2 + AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,""); + if(sub_frame == 0) { + UE->proc.proc_rxtx[0].frame_rx++; + UE->proc.proc_rxtx[1].frame_rx++; + } + UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs); + UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs); + proc->subframe_rx=sub_frame; + proc->subframe_tx=(sub_frame+4)%10; + proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0); + proc->timestamp_tx = timestamp+ + (4*UE->frame_parms.samples_per_tti)- + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; + + proc->instance_cnt_rxtx++; + if (proc->instance_cnt_rxtx == 0) { + if (pthread_cond_signal(&proc->cond_rxtx) != 0) { + LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\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_rxtx); + if (proc->instance_cnt_rxtx > 2) + exit_fun("instance_cnt_rxtx > 2"); + } + + AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,""); + AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,""); + initRefTimes(t1); + initStaticTime(lastTime); + updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)"); + pickStaticTime(lastTime); + + } else { + printf("Processing subframe %d",proc->subframe_rx); + getchar(); + } + } // start_rx_stream==1 + } // UE->is_synchronized==1 + + } // while !oai_exit + return NULL; } -*/ - /*! * \brief Initialize the UE theads. * Creates the UE threads: @@ -1690,126 +846,100 @@ void *UE_thread_old(void *arg) * - UE_thread_synch * and the locking between them. */ -void init_UE_threads(int inst) -{ - PHY_VARS_UE *UE; - - UE = PHY_vars_UE_g[inst][0]; - - pthread_attr_init (&UE->proc.attr_ue); - pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN); - -#ifndef LOWLATENCY - UE->proc.sched_param_ue.sched_priority = sched_get_priority_max(SCHED_FIFO); - pthread_attr_setschedparam(&UE->proc.attr_ue,&sched_param_UE_thread); -#endif +void init_UE_threads(PHY_VARS_UE *UE) { + struct rx_tx_thread_data *rtd; + + pthread_attr_init (&UE->proc.attr_ue); + pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN); + + pthread_mutex_init(&UE->proc.mutex_synch,NULL); + pthread_cond_init(&UE->proc.cond_synch,NULL); + + // the threads are not yet active, therefore access is allowed without locking + int nb_threads=2; + for (int i=0; i<nb_threads; i++) { + rtd = calloc(1, sizeof(struct rx_tx_thread_data)); + if (rtd == NULL) abort(); + rtd->UE = UE; + rtd->proc = &UE->proc.proc_rxtx[i]; + pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL); + UE->proc.proc_rxtx[i].sub_frame_start=i; + UE->proc.proc_rxtx[i].sub_frame_step=nb_threads; + pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd); + } + pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE); - // the threads are not yet active, therefore access is allowed without locking - UE->proc.proc_rxtx[0].instance_cnt_rxtx = -1; - UE->proc.proc_rxtx[1].instance_cnt_rxtx = -1; - UE->proc.proc_rxtx[0].proc_id = 0; - UE->proc.proc_rxtx[1].proc_id = 1; - UE->proc.instance_cnt_synch = -1; - pthread_mutex_init(&UE->proc.proc_rxtx[0].mutex_rxtx,NULL); - pthread_mutex_init(&UE->proc.proc_rxtx[1].mutex_rxtx,NULL); - pthread_mutex_init(&UE->proc.mutex_synch,NULL); - pthread_cond_init(&UE->proc.proc_rxtx[0].cond_rxtx,NULL); - pthread_cond_init(&UE->proc.proc_rxtx[1].cond_rxtx,NULL); - pthread_cond_init(&UE->proc.cond_synch,NULL); - pthread_create(&UE->proc.proc_rxtx[0].pthread_rxtx,NULL,UE_thread_rxn_txnp4,(void*)&UE->proc.proc_rxtx[0]); - pthread_setname_np( UE->proc.proc_rxtx[0].pthread_rxtx, "rxn_txnp4_even" ); - pthread_create(&UE->proc.proc_rxtx[1].pthread_rxtx,NULL,UE_thread_rxn_txnp4,(void*)&UE->proc.proc_rxtx[1]); - pthread_setname_np( UE->proc.proc_rxtx[1].pthread_rxtx, "rxn_txnp4_odd" ); - pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE); - pthread_setname_np( UE->proc.pthread_synch, "UE_thread_synch" ); } #ifdef OPENAIR2 -void fill_ue_band_info(void) -{ - - UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability; - int i,j; - - bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count; - - for (i=0; i<bands_to_scan.nbands; i++) { - - for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++) - if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) { - memcpy(&bands_to_scan.band_info[i], - &eutra_bands[j], - sizeof(eutra_band_t)); - - printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n", - bands_to_scan.band_info[i].band, - UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA, - bands_to_scan.band_info[i].dl_min, - bands_to_scan.band_info[i].dl_max, - bands_to_scan.band_info[i].ul_min, - bands_to_scan.band_info[i].ul_max, - (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD"); - break; - } - } +void fill_ue_band_info(void) { + + UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability; + int i,j; + + bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count; + + for (i=0; i<bands_to_scan.nbands; i++) { + + for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++) + if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) { + memcpy(&bands_to_scan.band_info[i], + &eutra_bands[j], + sizeof(eutra_band_t)); + + printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n", + bands_to_scan.band_info[i].band, + UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA, + bands_to_scan.band_info[i].dl_min, + bands_to_scan.band_info[i].dl_max, + bands_to_scan.band_info[i].ul_min, + bands_to_scan.band_info[i].ul_max, + (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD"); + break; + } + } } #endif -int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) -{ +int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) { - int i, CC_id; - LTE_DL_FRAME_PARMS *frame_parms; - openair0_rf_map *rf_map; + int i, CC_id; + LTE_DL_FRAME_PARMS *frame_parms; + openair0_rf_map *rf_map; - for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - rf_map = &phy_vars_ue[CC_id]->rf_map; - - if (phy_vars_ue[CC_id]) { - frame_parms = &(phy_vars_ue[CC_id]->frame_parms); - } else { - printf("phy_vars_UE[%d] not initialized\n", CC_id); - return(-1); - } - - /* - if (frame_parms->frame_type == TDD) { - if (frame_parms->N_RB_DL == 100) - N_TA_offset = 624; - else if (frame_parms->N_RB_DL == 50) - N_TA_offset = 624/2; - else if (frame_parms->N_RB_DL == 25) - N_TA_offset = 624/4; - } - */ - - // replace RX signal buffers with mmaped HW versions - rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - - for (i=0; i<frame_parms->nb_antennas_rx; i++) { - printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i ); - free( phy_vars_ue[CC_id]->common_vars.rxdata[i] ); - rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD - printf("rxdata[%d] : %p\n",i,rxdata[i]); - } - - for (i=0; i<frame_parms->nb_antennas_tx; i++) { - printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i ); - free( phy_vars_ue[CC_id]->common_vars.txdata[i] ); - txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i]; - printf("txdata[%d] : %p\n",i,txdata[i]); - } - - // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x] - // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x] - // be careful when releasing memory! - // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) - - } + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + rf_map = &phy_vars_ue[CC_id]->rf_map; + + AssertFatal( phy_vars_ue[CC_id] !=0, ""); + frame_parms = &(phy_vars_ue[CC_id]->frame_parms); + + // replace RX signal buffers with mmaped HW versions + rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + + for (i=0; i<frame_parms->nb_antennas_rx; i++) { + LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", + CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i ); + free( phy_vars_ue[CC_id]->common_vars.rxdata[i] ); + rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); + phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD + } - return 0; + for (i=0; i<frame_parms->nb_antennas_tx; i++) { + LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", + CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i ); + free( phy_vars_ue[CC_id]->common_vars.txdata[i] ); + txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); + phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i]; + } + + // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x] + // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x] + // be careful when releasing memory! + // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) + } + return 0; } + diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index 4abdaa243d2045c79d5d4236148a7de944fdc84e..e73c9ef4ebe0455db9a51b4c74dd908994df0cdf 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -65,7 +65,7 @@ /* local IP/MAC address is detected*/ char rrh_ip[20] = "0.0.0.0"; -unsigned char rrh_mac[6] = "0:0:0:0:0:0"; +unsigned char rrh_mac[20] = "0:0:0:0:0:0"; int rrh_port = 50000; // has to be an option /* log */ @@ -197,7 +197,7 @@ static rrh_module_t new_module (unsigned int id) { openair0_cfg.my_port = rrh_port; LOG_I(RRH,"UDP mode selected for ethernet.\n"); } else if (eth_mode==ETH_RAW_MODE) { - openair0_cfg.my_addr = &rrh_mac[0]; + openair0_cfg.my_addr = (char*)&rrh_mac[0]; openair0_cfg.my_port = rrh_port; LOG_I(RRH,"RAW mode selected for ethernet.\n"); } @@ -342,7 +342,7 @@ static int get_address(char* if_name, uint8_t flag) { perror("IOCTL:"); exit(-1); } - ether_ntoa_r ((unsigned char *)ifr.ifr_hwaddr.sa_data, rrh_mac); + ether_ntoa_r ((struct ether_addr *)ifr.ifr_hwaddr.sa_data, (char*)rrh_mac); LOG_I(RRH,"%s: MAC address: %s\n",if_name,rrh_mac); } @@ -376,7 +376,7 @@ void *timer_proc(void *arg) { timer_t timerid; struct itimerspec *timer= (struct itimerspec *)arg ; // the timer data structure - struct itimerspec *old_value; + struct itimerspec old_value; #ifdef DEADLINE_SCHEDULER @@ -407,7 +407,7 @@ void *timer_proc(void *arg) { signal(SIGALRM, timer_signal_handler); LOG_I(RRH,"Timer has started!\n"); - timer_settime (timerid, 0, timer, old_value); + timer_settime (timerid, 0, timer, &old_value); while (!rrh_exit) { sleep(1); diff --git a/targets/RT/USER/rt_wrapper.h b/targets/RT/USER/rt_wrapper.h index ca0507e003ffd0c84d5160aff8a5d06b057ec67f..28466524ac19ace950b24578ecbdffcc9000eaa7 100644 --- a/targets/RT/USER/rt_wrapper.h +++ b/targets/RT/USER/rt_wrapper.h @@ -30,7 +30,8 @@ * \warning This code will be removed when a legacy libc API becomes available. */ - +#ifndef _RT_WRAPPER_H_ +#define _RT_WRAPPER_H_ #define _GNU_SOURCE #include <time.h> @@ -121,3 +122,4 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned #define gettid() syscall(__NR_gettid) // for gettid +#endif /* _RT_WRAPPER_H_ */ diff --git a/targets/SIMU/PROC/Process.c b/targets/SIMU/PROC/Process.c index ee3d6d5c53ceee0d7072cb89ccf9c658d2bfe5ef..9d80c74d99bd70faf341d1f62e3c38672de3b062 100644 --- a/targets/SIMU/PROC/Process.c +++ b/targets/SIMU/PROC/Process.c @@ -284,8 +284,12 @@ void Channel_Inst(int node_id,int port,double **s_re[MAX_eNB+MAX_UE],double **s_ u2e_t[UE_id][eNB_id]->next_slot=&next_slot; u2e_t[UE_id][eNB_id]->abstraction_flag=&abstraction_flag; u2e_t[UE_id][eNB_id]->frame_parms=frame_parms; - u2e_t[UE_id][eNB_id]->tx_data[3]=tx[eNB_id][3]; - u2e_t[UE_id][eNB_id]->rx_data[3]=rx[NB_eNB_INST+UE_id][3]; + + for (int i=0;i<3;i++) + { + u2e_t[UE_id][eNB_id]->tx_data[i]=tx[eNB_id][i]; + u2e_t[UE_id][eNB_id]->rx_data[i]=rx[NB_eNB_INST+UE_id][i]; + } if(pthread_cond_init (&downlink_cond[eNB_id][UE_id], NULL)) exit(1); @@ -316,8 +320,11 @@ void Channel_Inst(int node_id,int port,double **s_re[MAX_eNB+MAX_UE],double **s_ e2u_t[eNB_id][UE_id]->next_slot=&next_slot; e2u_t[eNB_id][UE_id]->abstraction_flag=&abstraction_flag; e2u_t[eNB_id][UE_id]->frame_parms=frame_parms; - e2u_t[eNB_id][UE_id]->tx_data[3]=tx[NB_eNB_INST+UE_id][3]; - e2u_t[eNB_id][UE_id]->rx_data[3]=rx[eNB_id][3]; + for (int i=0;i<3;i++) + { + e2u_t[eNB_id][UE_id]->tx_data[i]=tx[NB_eNB_INST+UE_id][i]; + e2u_t[eNB_id][UE_id]->rx_data[i]=rx[eNB_id][i]; + } if(pthread_cond_init (&uplink_cond[UE_id][eNB_id], NULL)) exit(1); diff --git a/targets/SIMU/PROC/channel_sim_proc.c b/targets/SIMU/PROC/channel_sim_proc.c index 0ffdd97ce09501304c79bc1928ad8e27b611bcb4..b54fe36460cbe2831747d9984278d31716d3c920 100644 --- a/targets/SIMU/PROC/channel_sim_proc.c +++ b/targets/SIMU/PROC/channel_sim_proc.c @@ -183,8 +183,13 @@ void do_DL_sig_channel_T(void *param) next_slot=(cthread->next_slot); abstraction_flag=*(cthread->abstraction_flag); thread_id=(cthread->thread_id); - tx_data[3]=cthread->tx_data[3]; - rx_data[3]=cthread->rx_data[3]; + + for (int i=0;i<3;i++) + { + tx_data[i]=cthread->tx_data[i]; + rx_data[i]=cthread->rx_data[i]; + } + s32 att_eNB_id=-1; s32 **txdata,**rxdata; diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c index 370e50d145257253df3662f8e2dc80f0177a2799..04d7e1d2331fec3bd8f11b05249ef7cb1ab8f110 100644 --- a/targets/SIMU/USER/channel_sim.c +++ b/targets/SIMU/USER/channel_sim.c @@ -145,7 +145,7 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N // find out which eNB the UE is attached to for (eNB_id=0; eNB_id<NB_eNB_INST; eNB_id++) { - if (find_ue(PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti,PHY_vars_eNB_g[eNB_id][CC_id])>=0) { + if (find_ue(PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0][0]->crnti,PHY_vars_eNB_g[eNB_id][CC_id])>=0) { // UE with UE_id is connected to eNb with eNB_id att_eNB_id=eNB_id; LOG_D(OCM,"A: UE attached to eNB (UE%d->eNB%d)\n",UE_id,eNB_id); @@ -281,7 +281,7 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr %f dBm/RE (%f dBm RSSI)for subframe %d\n",UE_id, 10*log10(rx_pwr), 10*log10(rx_pwr*(double)frame_parms->N_RB_DL*12),subframe); - LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (noise) -132 dBm/RE (N0fs = %.1f dBm, N0B = %.1f dBm) for slot %d (subframe %d)\n", + LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (noise) -132 dBm/RE (N0fs = %.1f dBm, N0B = %.1f dBm) for subframe %d\n", UE_id, 10*log10(eNB2UE[eNB_id][UE_id][CC_id]->sampling_rate*1e6)-174, 10*log10(eNB2UE[eNB_id][UE_id][CC_id]->sampling_rate*1e6*12*frame_parms->N_RB_DL/(double)frame_parms->ofdm_symbol_size)-174, @@ -327,8 +327,8 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N eNB_output_mask[UE_id]=0; - double *r_re_p[2] = {r_re_DL[eNB_id][0],r_re_DL[eNB_id][1]}; - double *r_im_p[2] = {r_im_DL[eNB_id][0],r_im_DL[eNB_id][1]}; + double *r_re_p[2] = {r_re_DL[UE_id][0],r_re_DL[UE_id][1]}; + double *r_im_p[2] = {r_im_DL[UE_id][0],r_im_DL[UE_id][1]}; #ifdef DEBUG_SIM rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->ofdm_symbol_size,sf_offset)/(12.0*frame_parms->N_RB_DL); diff --git a/targets/SIMU/USER/event_handler.c b/targets/SIMU/USER/event_handler.c index f2199ca910b311099e554027619aa010dffe5486..c140dab50b6fd4bf4530354c3b85e0e5ae194db9 100644 --- a/targets/SIMU/USER/event_handler.c +++ b/targets/SIMU/USER/event_handler.c @@ -513,7 +513,7 @@ void update_mac(Event_t event) if(&mac_config[i].mac_ContentionResolutionTimer !=NULL) { oai_emulation->mac_config[i].mac_ContentionResolutionTimer= mac_config[i].mac_ContentionResolutionTimer; UE_list->UE_sched_ctrl[i].mac_ContentionResolutionTimer = oai_emulation->mac_config[i].mac_ContentionResolutionTimer; - LOG_I(EMU,"mac_ContentionResolutionTimer UE %:", i); + LOG_I(EMU,"mac_ContentionResolutionTimer UE %d:", i); LOG_I(EMU,"%" PRIu8 "\n",UE_list->UE_sched_ctrl[i].mac_ContentionResolutionTimer); } @@ -637,7 +637,7 @@ void update_mac(Event_t event) if(&mac_config[i].mac_ContentionResolutionTimer !=NULL) { oai_emulation->mac_config[i].mac_ContentionResolutionTimer= mac_config[i].mac_ContentionResolutionTimer; UE_list->UE_sched_ctrl[i].mac_ContentionResolutionTimer = oai_emulation->mac_config[i].mac_ContentionResolutionTimer; - LOG_I(EMU,"mac_ContentionResolutionTimer UE %:", i); + LOG_I(EMU,"mac_ContentionResolutionTimer UE %d:", i); LOG_I(EMU,"%" PRIu8 "\n",UE_list->UE_sched_ctrl[i].mac_ContentionResolutionTimer); } @@ -903,13 +903,13 @@ void update_mac(Event_t event) for(i=UE_list->head; i>=0; i=UE_list->next[i]) { oai_emulation->mac_config[i].cqiSchedInterval= mac_config[i].cqiSchedInterval; UE_list->UE_sched_ctrl[i].cqiSchedInterval = oai_emulation->mac_config[i].cqiSchedInterval; - LOG_I(EMU,"cqiSchedInterval UE :\n", i); + LOG_I(EMU,"cqiSchedInterval UE %d:\n", i); LOG_I(EMU,"%" PRIu16 "\n",UE_list->UE_sched_ctrl[i].cqiSchedInterval); } } else { oai_emulation->mac_config[event.ue].cqiSchedInterval= mac_config[event.ue].cqiSchedInterval; UE_list->UE_sched_ctrl[event.ue].cqiSchedInterval = oai_emulation->mac_config[event.ue].cqiSchedInterval; - LOG_I(EMU,"cqiSchedInterval UE :\n", event.ue); + LOG_I(EMU,"cqiSchedInterval UE %d:\n", event.ue); LOG_I(EMU,"%" PRIu16 "\n",UE_list->UE_sched_ctrl[event.ue].cqiSchedInterval); } } else if(!strcmp((char *) event.key, "mac_ContentionResolutionTimer") && event.value!=NULL && validate_mac(event)) { @@ -923,13 +923,13 @@ void update_mac(Event_t event) for(i=UE_list->head; i>=0; i=UE_list->next[i]) { oai_emulation->mac_config[i].mac_ContentionResolutionTimer= mac_config[i].mac_ContentionResolutionTimer; UE_list->UE_sched_ctrl[i].mac_ContentionResolutionTimer = oai_emulation->mac_config[i].mac_ContentionResolutionTimer; - LOG_I(EMU,"mac_ContentionResolutionTimer UE :\n", i); + LOG_I(EMU,"mac_ContentionResolutionTimer UE %d:\n", i); LOG_I(EMU,"%" PRIu8 "\n",UE_list->UE_sched_ctrl[i].mac_ContentionResolutionTimer); } } else { oai_emulation->mac_config[event.ue].mac_ContentionResolutionTimer= mac_config[event.ue].mac_ContentionResolutionTimer; UE_list->UE_sched_ctrl[event.ue].mac_ContentionResolutionTimer = oai_emulation->mac_config[event.ue].mac_ContentionResolutionTimer; - LOG_I(EMU,"mac_ContentionResolutionTimer UE :\n", event.ue); + LOG_I(EMU,"mac_ContentionResolutionTimer UE %d:\n", event.ue); LOG_I(EMU,"%" PRIu8 "\n",UE_list->UE_sched_ctrl[event.ue].mac_ContentionResolutionTimer); } } else if(!strcmp((char *) event.key, "max_allowed_rbs") && event.value!=NULL && validate_mac(event)) { @@ -1040,7 +1040,7 @@ void update_sys_model(Event_t event) LOG_I(EMU,"free_space_model_parameters.pathloss_exponent %G\n",oai_emulation->environment_system_config.fading.free_space_model_parameters.pathloss_exponent); LOG_I(EMU,"free_space_model_parameters.pathloss_0_dB %G\n",oai_emulation->environment_system_config.fading.free_space_model_parameters.pathloss_0_dB); - LOG_I(EMU,"ricean_8tap.rice_factor_dB %G\n",oai_emulation->environment_system_config.fading.ricean_8tap.rice_factor_dB); + LOG_I(EMU,"ricean_8tap.rice_factor_dB %d\n",oai_emulation->environment_system_config.fading.ricean_8tap.rice_factor_dB); //Antenna LOG_I(EMU,"antenna.eNB_antenna.number_of_sectors %d\n",oai_emulation->environment_system_config.antenna.eNB_antenna.number_of_sectors); @@ -1103,7 +1103,7 @@ void update_sys_model(Event_t event) } else if(!strcmp((char *) event.key, "free_space_model_parameters.pathloss_0_dB")) { LOG_I(EMU,"free_space_model_parameters.pathloss_0_dB %G\n",oai_emulation->environment_system_config.fading.free_space_model_parameters.pathloss_0_dB); } else if(!strcmp((char *) event.key, "ricean_8tap.rice_factor_dB")) { - LOG_I(EMU,"ricean_8tap.rice_factor_dB %G\n",oai_emulation->environment_system_config.fading.ricean_8tap.rice_factor_dB); + LOG_I(EMU,"ricean_8tap.rice_factor_dB %d\n",oai_emulation->environment_system_config.fading.ricean_8tap.rice_factor_dB); } else if(!strcmp((char *) event.key, "antenna.eNB_antenna.number_of_sectors")) { LOG_I(EMU,"antenna.eNB_antenna.number_of_sectors %d\n",oai_emulation->environment_system_config.antenna.eNB_antenna.number_of_sectors); } else if(!strcmp((char *) event.key, "antenna.eNB_antenna.beam_width_dB")) { @@ -1202,8 +1202,8 @@ void update_topo_model(Event_t event) LOG_I(EMU,"UE_moving_dynamics_max_speed_mps %G\n",oai_emulation->topology_config.mobility.UE_mobility.UE_moving_dynamics.max_speed_mps); LOG_I(EMU,"UE_moving_dynamics_min_journey_time_ms %G\n",oai_emulation->topology_config.mobility.UE_mobility.UE_moving_dynamics.min_journey_time_ms); LOG_I(EMU,"UE_moving_dynamics_max_journey_time_ms %G\n",oai_emulation->topology_config.mobility.UE_mobility.UE_moving_dynamics.max_journey_time_ms); - LOG_I(EMU,"grid_map_horizontal_grid %G\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.horizontal_grid); - LOG_I(EMU,"grid_map_vertical_grid %G\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.vertical_grid); + LOG_I(EMU,"grid_map_horizontal_grid %d\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.horizontal_grid); + LOG_I(EMU,"grid_map_vertical_grid %d\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.vertical_grid); LOG_I(EMU,"UE_initial_distribution_selected_option %s\n",oai_emulation->topology_config.mobility.UE_mobility.UE_initial_distribution.selected_option); LOG_I(EMU,"random_UE_distribution_number_of_nodes %d\n",oai_emulation->topology_config.mobility.UE_mobility.random_UE_distribution.number_of_nodes); LOG_I(EMU,"concentrated_UE_distribution_number_of_nodes %d\n",oai_emulation->topology_config.mobility.UE_mobility.concentrated_UE_distribution.number_of_nodes); @@ -1245,9 +1245,9 @@ void update_topo_model(Event_t event) } else if(!strcmp((char *) event.key, "UE_moving_dynamics_max_journey_time_ms")) { LOG_I(EMU,"UE_moving_dynamics_max_journey_time_ms %G\n",oai_emulation->topology_config.mobility.UE_mobility.UE_moving_dynamics.max_journey_time_ms); } else if(!strcmp((char *) event.key, "grid_map_horizontal_grid")) { - LOG_I(EMU,"grid_map_horizontal_grid %G\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.horizontal_grid); + LOG_I(EMU,"grid_map_horizontal_grid %d\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.horizontal_grid); } else if(!strcmp((char *) event.key, "grid_map_vertical_grid")) { - LOG_I(EMU,"grid_map_vertical_grid %G\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.vertical_grid); + LOG_I(EMU,"grid_map_vertical_grid %d\n",oai_emulation->topology_config.mobility.UE_mobility.grid_walk.grid_map.vertical_grid); } else if(!strcmp((char *) event.key, "UE_initial_distribution_selected_option")) { LOG_I(EMU,"UE_initial_distribution_selected_option %s\n",oai_emulation->topology_config.mobility.UE_mobility.UE_initial_distribution.selected_option); } else if(!strcmp((char *) event.key, "random_UE_distribution_number_of_nodes")) { diff --git a/targets/SIMU/USER/init_lte.c b/targets/SIMU/USER/init_lte.c index 62273185b23445b689c6ae6774cbc763aa420253..3baf8fdad66b285b0019d4e7fb08cad62a499c4a 100644 --- a/targets/SIMU/USER/init_lte.c +++ b/targets/SIMU/USER/init_lte.c @@ -81,7 +81,7 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, } } - LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n"); + LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n", i); PHY_vars_eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,frame_parms->N_RB_UL, abstraction_flag); if (!PHY_vars_eNB->ulsch[1+i]) { @@ -162,29 +162,31 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, phy_init_lte_ue(PHY_vars_UE,1,abstraction_flag); for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { - for (j=0; j<2; j++) { - PHY_vars_UE->dlsch[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - - if (!PHY_vars_UE->dlsch[i][j]) { - LOG_E(PHY,"Can't get ue dlsch structures\n"); - exit(-1); - } else - LOG_D(PHY,"dlsch[%d][%d] => %p\n",UE_id,i,PHY_vars_UE->dlsch[i][j]); - } + for (j=0; j<2; j++) { // 2CWs + for (int l=0; l<2; l++){ // 2Threads + PHY_vars_UE->dlsch[l][i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + + if (!PHY_vars_UE->dlsch[l][i][j]) { + LOG_E(PHY,"Can't get ue dlsch structures\n"); + exit(-1); + } else + LOG_D(PHY,"dlsch[%d][%d] => %p\n",UE_id,i,PHY_vars_UE->dlsch[l][i][j]); + } + } - PHY_vars_UE->ulsch[i] = new_ue_ulsch(frame_parms->N_RB_UL, abstraction_flag); + PHY_vars_UE->ulsch[i] = new_ue_ulsch(frame_parms->N_RB_UL, abstraction_flag); - if (!PHY_vars_UE->ulsch[i]) { - LOG_E(PHY,"Can't get ue ulsch structures\n"); - exit(-1); - } + if (!PHY_vars_UE->ulsch[i]) { + LOG_E(PHY,"Can't get ue ulsch structures\n"); + exit(-1); + } - PHY_vars_UE->dlsch_SI[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - PHY_vars_UE->dlsch_ra[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_SI[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ra[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - PHY_vars_UE->transmission_mode[i] = frame_parms->nb_antenna_ports_eNB==1 ? 1 : 2; + PHY_vars_UE->transmission_mode[i] = frame_parms->nb_antenna_ports_eNB==1 ? 1 : 2; } PHY_vars_UE->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c index 71bfce44cb1a1ce2ef54927491d10c07ac8e6ed1..d07cd759d1c84885d0987b1bc38865bb7e46fbb3 100644 --- a/targets/SIMU/USER/oaisim.c +++ b/targets/SIMU/USER/oaisim.c @@ -59,6 +59,7 @@ #include "SCHED/defs.h" #include "SCHED/vars.h" +#include "system.h" #include "PHY/TOOLS/lte_phy_scope.h" @@ -181,7 +182,9 @@ extern uint16_t Nid_cell; extern LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; - +double cpuf; +#include "threads_t.h" +threads_t threads= {-1,-1,-1}; //#ifdef XFORMS int otg_enabled; @@ -240,7 +243,7 @@ help (void) printf ("-L [0-1] 0 to disable new link adaptation, 1 to enable new link adapatation\n"); printf ("-m Gives a fixed DL mcs for eNB scheduler\n"); printf ("-M Set the machine ID for Ethernet-based emulation\n"); - printf ("-n Set the number of frames for the simulation\n"); + printf ("-n Set the number of frames for the simulation. 0 for no limit\n"); printf ("-O [enb_conf_file] eNB configuration file name\n"); printf ("-p Set the total number of machine in emulation - valid if M is set\n"); printf ("-P [trace type] Enable protocol analyzer. Possible values for OPT:\n"); @@ -457,7 +460,8 @@ l2l1_task_state_t l2l1_state = L2L1_WAITTING; extern openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs]; - +extern openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; +extern openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs]; /*------------------------------------------------------------------------------*/ void * @@ -469,7 +473,7 @@ l2l1_task (void *args_p) // Framing variables int32_t sf; - char fname[64], vname[64]; + //char fname[64], vname[64]; //#ifdef XFORMS // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) @@ -590,6 +594,7 @@ l2l1_task (void *args_p) switch (ITTI_MSG_ID(message_p)) { case INITIALIZE_MESSAGE: l2l1_state = L2L1_RUNNING; + start_eNB = 1; break; case ACTIVATE_MESSAGE: @@ -733,57 +738,43 @@ l2l1_task (void *args_p) clear_eNB_transport_info (oai_emulation.info.nb_enb_local); - CC_id=0; int all_done=0; while (all_done==0) { - pthread_mutex_lock(&subframe_mutex); - int subframe_eNB_mask_local = subframe_eNB_mask; - int subframe_UE_mask_local = subframe_UE_mask; - pthread_mutex_unlock(&subframe_mutex); - LOG_D(EMU,"Frame %d, Subframe %d: Checking masks %x,%x\n",frame,sf,subframe_eNB_mask,subframe_UE_mask); - if ((subframe_eNB_mask_local == ((1<<NB_eNB_INST)-1)) && - (subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) - all_done=1; - else - usleep(1500); + int i; + all_done = 1; + for (i = oai_emulation.info.first_enb_local; + i < oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local; + i++) + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + if (last_eNB_rx_timestamp[i][CC_id] != current_eNB_rx_timestamp[i][CC_id]) { + all_done = 0; + break; + } + if (all_done == 1) + for (i = 0; i < NB_UE_INST; i++) + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + if (last_UE_rx_timestamp[i][CC_id] != current_UE_rx_timestamp[i][CC_id]) { + all_done = 0; + break; + } + if (all_done == 0) + usleep(500); } - //clear subframe masks for next round - pthread_mutex_lock(&subframe_mutex); - subframe_eNB_mask=0; - subframe_UE_mask=0; - pthread_mutex_unlock(&subframe_mutex); - // increment timestamps for (eNB_inst = oai_emulation.info.first_enb_local; (eNB_inst < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)); eNB_inst++) { - - current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti; + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti; } for (UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) { - current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti; + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti; } - - if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) { - T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(slot/2)); - /* - LOG_D(EMU, - "PHY procedures eNB %d for frame %d, slot %d (subframe TX %d, RX %d) TDD %d/%d Nid_cell %d\n", - eNB_inst, - frame%MAX_FRAME_NUMBER, - 2*sf, - PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_tx, - PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_rx, - PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.frame_type, - PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.tdd_config, - PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.Nid_cell); - */ - } - for (eNB_inst = oai_emulation.info.first_enb_local; (eNB_inst < (oai_emulation.info.first_enb_local @@ -791,7 +782,6 @@ l2l1_task (void *args_p) eNB_inst++) { if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) { - T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(sf)); /* LOG_D(EMU, "PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n", @@ -940,7 +930,7 @@ l2l1_task (void *args_p) } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) for (RN_id=oai_emulation.info.first_rn_local; RN_id<oai_emulation.info.first_rn_local+oai_emulation.info.nb_rn_local; @@ -1198,6 +1188,15 @@ int T_port = 2021; /* default port to listen to to wait for the tracer */ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */ #endif +static void print_current_directory(void) +{ + char dir[8192]; /* arbitrary size (should be big enough) */ + if (getcwd(dir, 8192) == NULL) + printf("ERROR getting working directory\n"); + else + printf("working directory: %s\n", dir); +} + /*------------------------------------------------------------------------------*/ int main (int argc, char **argv) @@ -1205,6 +1204,10 @@ main (int argc, char **argv) clock_t t; + print_current_directory(); + + start_background_system(); + #ifdef SMBV // Rohde&Schwarz SMBV100A vector signal generator strcpy(smbv_ip,DEFAULT_SMBV_IP); @@ -1223,6 +1226,15 @@ main (int argc, char **argv) //Default values if not changed by the user in get_simulation_options(); pdcp_period = 1; omg_period = 1; + //Clean ip rule table + for(int i =0; i<NUMBER_OF_UE_MAX; i++){ + char command_line[100]; + sprintf(command_line, "while ip rule del table %d; do true; done",i+201); + /* we don't care about return value from system(), but let's the + * compiler be silent, so let's do "if (XX);" + */ + if (system(command_line)) /* nothing */; + } // start thread for log gen log_thread_init (); @@ -1291,13 +1303,12 @@ main (int argc, char **argv) init_openair2 (); + void init_openair0(void); init_openair0(); init_ocm (); #if defined(ENABLE_ITTI) - // Handle signals until all tasks are terminated - // Note: Cannot handle both RRU/RAU and eNB at the same time, if the first "eNB" is an RRU/RAU, no NAS if (oai_emulation.info.node_function[0] < NGFI_RAU_IF4p5) { if (create_tasks(oai_emulation.info.nb_enb_local, @@ -1339,6 +1350,8 @@ main (int argc, char **argv) if (oai_emulation.info.opp_enabled == 1) reset_opp_meas_oaisim (); + cpuf=get_cpu_freq_GHz(); + init_time (); init_slot_isr (); @@ -1348,11 +1361,16 @@ main (int argc, char **argv) LOG_N(EMU, ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU initialization done <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(EMU, "Version: %s\n", PACKAGE_VERSION); + #if defined(ENABLE_ITTI) + // Handle signals until all tasks are terminated itti_wait_tasks_end(); - #else if (oai_emulation.info.nb_enb_local > 0) { @@ -1388,14 +1406,16 @@ reset_opp_meas_oaisim (void) for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) { reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc); - reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx); + reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[0]); + reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[1]); reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx); reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats); reset_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats); reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats); reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats); - reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats); + reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[0]); + reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[1]); reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats); reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats); reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats); @@ -1557,8 +1577,10 @@ print_opp_meas_oaisim (void) print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc, "[UE][total_phy_proc]", &oaisim_stats, &oaisim_stats_f); - print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx, - "[UE][total_phy_proc_rx]", &oaisim_stats, &oaisim_stats_f); + print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[0], + "[UE][total_phy_proc_rx[0]]", &oaisim_stats, &oaisim_stats_f); + print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[1], + "[UE][total_phy_proc_rx[1]]", &oaisim_stats, &oaisim_stats_f); print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats, "[UE][ofdm_demod]", &oaisim_stats, &oaisim_stats_f); print_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats, "[UE][rx_dft]", @@ -1571,8 +1593,10 @@ print_opp_meas_oaisim (void) &oaisim_stats, &oaisim_stats_f); print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats, "[UE][unscrambling]", &oaisim_stats, &oaisim_stats_f); - print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats, - "[UE][decoding]", &oaisim_stats, &oaisim_stats_f); + print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[0], + "[UE][decoding[0]]", &oaisim_stats, &oaisim_stats_f); + print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[1], + "[UE][decoding[1]]", &oaisim_stats, &oaisim_stats_f); print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats, "[UE][rate_unmatching]", &oaisim_stats, &oaisim_stats_f); print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats, diff --git a/targets/SIMU/USER/oaisim_config.c b/targets/SIMU/USER/oaisim_config.c index e3aac4f481aec3d6723955fd956ee10183526621..70728875f590b985683821b81eaf007f1dcdc3da 100644 --- a/targets/SIMU/USER/oaisim_config.c +++ b/targets/SIMU/USER/oaisim_config.c @@ -468,7 +468,7 @@ int ocg_config_env(void) oai_emulation.info.frame_type[CC_id] = map_str_to_int(frame_type_names, oai_emulation.info.frame_type_name[CC_id]); if (oai_emulation.info.frame_type[CC_id] == -1) { - LOG_E(EMU,"frame type incorrect %s, set it to TDD \n",oai_emulation.info.frame_type_name); + LOG_E(EMU,"frame type incorrect %s, set it to TDD \n",oai_emulation.info.frame_type_name[CC_id]); oai_emulation.info.frame_type[CC_id]=TDD; } else LOG_I(EMU,"Frame type is %s \n",oai_emulation.info.frame_type_name[CC_id]); @@ -478,7 +478,7 @@ int ocg_config_env(void) LOG_E(EMU,"TDD config %d out of range, set it to 3\n",oai_emulation.info.tdd_config[CC_id]); oai_emulation.info.tdd_config[CC_id]=3; } else - LOG_I(EMU,"TDD config is set to \n",oai_emulation.info.tdd_config[CC_id]); + LOG_I(EMU,"TDD config is set to %d\n",oai_emulation.info.tdd_config[CC_id]); } } } @@ -1087,8 +1087,8 @@ int ocg_config_app(void) oai_emulation.application_config.customized_traffic.holding_time_pe_off[customized_traffic_config_index]; - LOG_I(OTG,"customized:: OCG_config_OTG: (2) FORMAT (%d:%d) source = %d, dest = %d, dist type for size = %d start/duration %d/%d\n", source_id_start, source_id_end, source_id_index, - destination_id_index, g_otg->size_dist[source_id_index][destination_id_index][0], + LOG_I(OTG,"customized:: OCG_config_OTG: (2) FORMAT (%s:%s) source = %d, dest = %d, dist type for size = %d [TODO: check code, printed value may not be correct, checks the indexes of the arry access] start/duration %d/%d\n", source_id_start, source_id_end, source_id_index, + destination_id_index, g_otg->size_dist[source_id_index][destination_id_index][0][0], g_otg->flow_start[source_id_index][destination_id_index][g_otg->application_idx[source_id_index][destination_id_index]], g_otg->flow_duration[source_id_index][destination_id_index][g_otg->application_idx[source_id_index][destination_id_index]]); per_source_id = strtok(NULL, comma); diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 7fa29843bea688633d309a0f32bc2525330505c8..71304aea8ece1c2e35a4a1f9ffbb35b121e2a29c 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -21,7 +21,7 @@ /*! \file oaisim_functions.c * \brief function primitives of oaisim -* \author Navid Nikaein +* \author Navid Nikaein * \date 2013-2015 * \version 1.0 * \company Eurecom @@ -91,7 +91,9 @@ extern char smbv_ip[16]; #define K 2 // averaging coefficient #define TARGET_SF_TIME_NS 1000000 // 1ms = 1000000 ns +#ifndef min #define min(a,b) ((a)<(b)?(a):(b)) +#endif int otg_times = 0; int if_times = 0; @@ -161,7 +163,7 @@ extern channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs]; extern channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; extern mapping small_scale_names[]; -#if defined(Rel10) +#if defined(Rel10) || defined(Rel14) extern pdcp_mbms_t pdcp_mbms_array_ue[NUMBER_OF_UE_MAX][maxServiceCount][maxSessionPerPMCH]; extern pdcp_mbms_t pdcp_mbms_array_eNB[NUMBER_OF_eNB_MAX][maxServiceCount][maxSessionPerPMCH]; #endif @@ -729,8 +731,9 @@ void get_simulation_options(int argc, char *argv[]) /* oai_emulation.info.transmission_mode[0] = atoi (optarg); - if ((oai_emulation.info.transmission_mode[0] != 1) && (oai_emulation.info.transmission_mode[0] != 2) && (oai_emulation.info.transmission_mode[0] != 3) - && (oai_emulation.info.transmission_mode[0] != 5) && (oai_emulation.info.transmission_mode[0] != 6) && (oai_emulation.info.transmission_mode[0] !=7)) { + if ((oai_emulation.info.transmission_mode[0] != 1) && (oai_emulation.info.transmission_mode[0] != 2) && + (oai_emulation.info.transmission_mode[0] != 3) && (oai_emulation.info.transmission_mode[0] != 4) && + (oai_emulation.info.transmission_mode[0] != 5) && (oai_emulation.info.transmission_mode[0] != 6)) && (oai_emulation.info.transmission_mode[0] !=7)) { printf("Unsupported transmission mode %d\n",oai_emulation.info.transmission_mode[0]); exit(-1); } @@ -1013,8 +1016,8 @@ int eNB_trx_stop(openair0_device *device) { int UE_trx_start(openair0_device *device) { return(0); } -int UE_trx_end(openair0_device *device) { - return(0); +void UE_trx_end(openair0_device *device) { + return; } int UE_trx_stop(openair0_device *device) { return(0); @@ -1035,65 +1038,73 @@ int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { extern pthread_mutex_t subframe_mutex; extern int subframe_eNB_mask,subframe_UE_mask; -int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - +int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) +{ + int ret = nsamps; int eNB_id = device->Mod_id; int CC_id = device->CC_id; int subframe; - int sample_count=0; + int read_samples, max_samples; + openair0_timestamp last = last_eNB_rx_timestamp[eNB_id][CC_id]; *ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id]; - LOG_D(EMU,"eNB_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps, - (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id], - (unsigned long long)last_eNB_rx_timestamp[eNB_id][CC_id], - (*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10); + LOG_D(EMU,"eNB_trx_read nsamps %d TS(%"PRId64",%"PRId64") => subframe %d\n",nsamps, + current_eNB_rx_timestamp[eNB_id][CC_id], + last_eNB_rx_timestamp[eNB_id][CC_id], + (int)((*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10)); // if we're at a subframe boundary generate UL signals for this eNB - while (sample_count<nsamps) { - while (current_eNB_rx_timestamp[eNB_id][CC_id]< - (nsamps+last_eNB_rx_timestamp[eNB_id][CC_id])) { - // LOG_D(EMU,"eNB: current TS %llu, last TS %llu, sleeping\n",current_eNB_rx_timestamp[eNB_id][CC_id],last_eNB_rx_timestamp[eNB_id][CC_id]); + while (nsamps) { + while (current_eNB_rx_timestamp[eNB_id][CC_id] == last) { + LOG_D(EMU,"eNB: current TS %"PRId64", last TS %"PRId64", sleeping\n",current_eNB_rx_timestamp[eNB_id][CC_id],last_eNB_rx_timestamp[eNB_id][CC_id]); usleep(500); } - // tell top-level we are busy - pthread_mutex_lock(&subframe_mutex); - subframe_eNB_mask|=(1<<eNB_id); - pthread_mutex_unlock(&subframe_mutex); - - subframe = (last_eNB_rx_timestamp[eNB_id][CC_id]/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10; - LOG_D(EMU,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n", - subframe,(unsigned long long)*ptimestamp, - (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]); + read_samples = nsamps; + max_samples = current_eNB_rx_timestamp[eNB_id][CC_id]-last; + if (read_samples > max_samples) + read_samples = max_samples; + + last += read_samples; + nsamps -= read_samples; + + if (current_eNB_rx_timestamp[eNB_id][CC_id] == last) { + subframe = (last/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10; + //subframe = (subframe+9) % 10; + + LOG_D(PHY,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n", + subframe,(unsigned long long)*ptimestamp, + (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]); - do_UL_sig(UE2eNB, - enb_data, - ue_data, - subframe, - 0, // abstraction_flag - &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms, - 0, // frame is only used for abstraction - eNB_id, - CC_id); - - last_eNB_rx_timestamp[eNB_id][CC_id] += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; - sample_count += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; + do_UL_sig(UE2eNB, + enb_data, + ue_data, + subframe, + 0, // abstraction_flag + &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms, + 0, // frame is only used for abstraction + eNB_id, + CC_id); + + last_eNB_rx_timestamp[eNB_id][CC_id] = last; + } } + last_eNB_rx_timestamp[eNB_id][CC_id] = last; - - return(nsamps); + return ret; } -int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - +int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) +{ + int ret = nsamps; int UE_id = device->Mod_id; int CC_id = device->CC_id; int subframe; - int sample_count=0; - int read_size; + int read_samples, max_samples; + openair0_timestamp last = last_UE_rx_timestamp[UE_id][CC_id]; *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id]; @@ -1102,55 +1113,59 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id], cc); - if (nsamps < PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) - read_size = nsamps; - else - read_size = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti; - - while (sample_count<nsamps) { - while (current_UE_rx_timestamp[UE_id][CC_id] < - (last_UE_rx_timestamp[UE_id][CC_id]+read_size)) { - //LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]); + while (nsamps) { + /* wait for all processing to be finished */ + while (1) { + PHY_VARS_UE *UE = PHY_vars_UE_g[UE_id][0]; + int ready = 1; + int i; + for (i = 0; i < 2; i++) + if (UE->proc.proc_rxtx[i].instance_cnt_rxtx >= 0) ready = 0; + if (UE->proc.instance_cnt_synch >= 0) ready = 0; + if (ready) break; + usleep(500); + } + while (current_UE_rx_timestamp[UE_id][CC_id] == last) { + LOG_D(EMU,"UE_trx_read : current TS %"PRId64", last TS %"PRId64", sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]); usleep(500); } // LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]); - // tell top-level we are busy - pthread_mutex_lock(&subframe_mutex); - subframe_UE_mask|=(1<<UE_id); - pthread_mutex_unlock(&subframe_mutex); - - - // otherwise we have one subframe here so generate the received signal - subframe = (last_UE_rx_timestamp[UE_id][CC_id]/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10; - if ((last_UE_rx_timestamp[UE_id][CC_id]%PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) > 0) - subframe++; - - last_UE_rx_timestamp[UE_id][CC_id] += read_size; - sample_count += read_size; - - if (subframe > 9) - return(nsamps); - - LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n", - subframe,(unsigned long long)*ptimestamp, - (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]); - do_DL_sig(eNB2UE, - enb_data, - ue_data, - subframe, - 0, //abstraction_flag, - &PHY_vars_UE_g[UE_id][CC_id]->frame_parms, - UE_id, - CC_id); - - + read_samples = nsamps; + max_samples = current_UE_rx_timestamp[UE_id][CC_id]-last; + if (read_samples > max_samples) + read_samples = max_samples; + + last += read_samples; + nsamps -= read_samples; + + if (current_UE_rx_timestamp[UE_id][CC_id] == last) { + // we have one subframe here so generate the received signal + subframe = (last/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10; + //subframe = (subframe+9) % 10; + + LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n", + subframe,(unsigned long long)*ptimestamp, + (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]); + + do_DL_sig(eNB2UE, + enb_data, + ue_data, + subframe, + 0, //abstraction_flag, + &PHY_vars_UE_g[UE_id][CC_id]->frame_parms, + UE_id, + CC_id); + + last_UE_rx_timestamp[UE_id][CC_id] = last; + } } + last_UE_rx_timestamp[UE_id][CC_id] = last; - return(nsamps); + return ret; } int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { @@ -1280,7 +1295,7 @@ void init_devices(void){ void init_openair1(void) { - module_id_t UE_id, eNB_id; + module_id_t UE_id, eNB_id = 0; uint8_t CC_id; #if ENABLE_RAL int list_index; @@ -1288,9 +1303,9 @@ void init_openair1(void) // change the nb_connected_eNB for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - init_lte_vars (&frame_parms[CC_id], - oai_emulation.info.frame_type[CC_id], - oai_emulation.info.tdd_config[CC_id], + init_lte_vars (&frame_parms[CC_id], + oai_emulation.info.frame_type[CC_id], + oai_emulation.info.tdd_config[CC_id], oai_emulation.info.tdd_config_S[CC_id], oai_emulation.info.extended_prefix_flag[CC_id], oai_emulation.info.N_RB_DL[CC_id], @@ -1396,9 +1411,9 @@ void init_openair1(void) // init_ue_status(); for (UE_id=0; UE_id<NB_UE_INST; UE_id++) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - + PHY_vars_UE_g[UE_id][CC_id]->tx_power_max_dBm=10; - + PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB=100; // update UE_mode for each eNB_id not just 0 @@ -1415,7 +1430,7 @@ void init_openair1(void) else PHY_vars_UE_g[UE_id][CC_id]->mac_enabled=1; - PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti = 0x1235 + UE_id; + PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0][0]->crnti = 0x1235 + UE_id; PHY_vars_UE_g[UE_id][CC_id]->current_dlsch_cqi[0] = 10; LOG_I(EMU, "UE %d mode is initialized to %d\n", UE_id, PHY_vars_UE_g[UE_id][CC_id]->UE_mode[0] ); @@ -1434,6 +1449,7 @@ void init_openair1(void) } // CC_id } // UE_id + extern void init_UE(int); init_UE(NB_UE_INST); } @@ -1470,7 +1486,7 @@ void init_ocm(void) break; case TDD: - frame_type = "FDD"; + frame_type = "TDD"; break; } @@ -1485,7 +1501,7 @@ void init_ocm(void) get_beta_map_up(); #endif get_MIESM_param(); - + //load_pbch_desc(); } @@ -1526,7 +1542,7 @@ void init_ocm(void) map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), eNB_id, UE_id); - eNB2UE[eNB_id][UE_id][CC_id] = + eNB2UE[eNB_id][UE_id][CC_id] = new_channel_desc_scm(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx, PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx, map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), @@ -1539,7 +1555,7 @@ void init_ocm(void) LOG_D(OCM,"[SIM] Initializing channel (%s, %d) from UE %d to eNB %d\n", oai_emulation.environment_system_config.fading.small_scale.selected_option, map_str_to_int(small_scale_names, oai_emulation.environment_system_config.fading.small_scale.selected_option),UE_id, eNB_id); - UE2eNB[UE_id][eNB_id][CC_id] = + UE2eNB[UE_id][eNB_id][CC_id] = new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx, PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_rx, map_str_to_int(small_scale_names, oai_emulation.environment_system_config.fading.small_scale.selected_option), @@ -1664,7 +1680,7 @@ void update_ocm() //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE if (eNB_id == (UE_id % NB_eNB_INST)) { eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; - UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; + UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; } else { eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; @@ -1673,7 +1689,7 @@ void update_ocm() LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",eNB_id,UE_id,CC_id, eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB, PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB); - + } } } @@ -1698,9 +1714,9 @@ void update_otg_eNB(module_id_t enb_module_idP, unsigned int ctime) // generate traffic if the ue is rrc reconfigured state //if ((rrc_state=mac_eNB_get_rrc_status(enb_module_idP, dst_id)) > 2 /*RRC_CONNECTED*/ ) { - if (mac_eNB_get_rrc_status(enb_module_idP, oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_idP][dst_id]) > 2 ){ + if (mac_eNB_get_rrc_status(enb_module_idP, oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_idP][dst_id]) > 2 ){ if_times += 1; - + for (app_id=0; app_id<MAX_NUM_APPLICATION; app_id++) { otg_pkt = malloc (sizeof(Packet_otg_elt_t)); @@ -1725,7 +1741,7 @@ void update_otg_eNB(module_id_t enb_module_idP, unsigned int ctime) } } -#ifdef Rel10 +#if defined(Rel10) || defined(Rel14) mbms_service_id_t service_id; mbms_session_id_t session_id; rb_id_t rb_id; @@ -1760,7 +1776,7 @@ void update_otg_eNB(module_id_t enb_module_idP, unsigned int ctime) // old version /* // MBSM multicast traffic - #ifdef Rel10 + #if defined(Rel10) || defined(Rel14) if (frame >= 46) {// only generate when UE can receive MTCH (need to control this value) for (service_id = 0; service_id < 2 ; service_id++) { //maxServiceCount for (session_id = 0; session_id < 2; session_id++) { // maxSessionPerPMCH @@ -1842,16 +1858,16 @@ void update_otg_UE(module_id_t ue_mod_idP, unsigned int ctime) if (mac_UE_get_rrc_status(ue_mod_idP, dst_id ) > 2 /*RRC_CONNECTED*/) { for (app_id=0; app_id<MAX_NUM_APPLICATION; app_id++) { Packet_otg_elt_t *otg_pkt = malloc (sizeof(Packet_otg_elt_t)); - + if (otg_pkt!=NULL) memset(otg_pkt,0,sizeof(Packet_otg_elt_t)); else { LOG_E(OTG,"not enough memory\n"); exit(-1); }// Manage to add this packet to the tail of your list - + (otg_pkt->otg_pkt).sdu_buffer = (uint8_t*) packet_gen(src_id, dst_id, app_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size)); - + if ((otg_pkt->otg_pkt).sdu_buffer != NULL) { (otg_pkt->otg_pkt).rb_id = DTCH-2; (otg_pkt->otg_pkt).module_id = module_id; diff --git a/targets/build_helper.bash b/targets/build_helper.bash index 163be3ba53504b764e21aebcccab1f76e5923246..f161275c65d09c1d9a7a5585ceed4326ead50460 100755 --- a/targets/build_helper.bash +++ b/targets/build_helper.bash @@ -852,8 +852,8 @@ compile_nas_tools() { fi echo_success "make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS/tools all" make --directory=$OPENAIR3_DIR/NAS/EURECOM-NAS/tools all - rm .ue.nvram - rm .usim.nvram + rm .ue.nvram0 + rm .usim.nvram0 touch /tmp/nas_cleaned } @@ -1027,13 +1027,13 @@ install_oaisim() { install_nas_tools() { cd $OPENAIR_TARGETS/bin - if [ ! -f .ue.nvram ]; then - echo_success "generate .ue_emm.nvram .ue.nvram" + if [ ! -f .ue.nvram0 ]; then + echo_success "generate .ue_emm.nvram0 .ue.nvram0" $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --gen fi - if [ ! -f .usim.nvram ]; then - echo_success "generate .usim.nvram" + if [ ! -f .usim.nvram0 ]; then + echo_success "generate .usim.nvram0" $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/usim_data --gen fi $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --print diff --git a/targets/build_oai.bash b/targets/build_oai.bash index 1303ef9e7e9cba90e231bb3e9203982fe3f2ded7..7a6a179bebc431acb4158b218cee4bcbd8d724ec 100755 --- a/targets/build_oai.bash +++ b/targets/build_oai.bash @@ -756,13 +756,13 @@ if [ $RUN -ne 0 ]; then install_nasmesh else # prepare NAS for UE - if [ ! -f .ue.nvram ]; then - echo_success "generate .ue_emm.nvram .ue.nvram" + if [ ! -f .ue.nvram0 ]; then + echo_success "generate .ue_emm.nvram0 .ue.nvram0" $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --gen fi - if [ ! -f .usim.nvram ]; then - echo_success "generate .usim.nvram" + if [ ! -f .usim.nvram0 ]; then + echo_success "generate .usim.nvram0" $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/usim_data --gen fi $OPENAIR3_DIR/NAS/EURECOM-NAS/bin/ue_data --print