Commit ac711d9a authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/rfsimu_config' into develop_integration_2019_w36

parents e45794ce 7a1a9f83
...@@ -57,6 +57,7 @@ pipeline { ...@@ -57,6 +57,7 @@ pipeline {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true def allParametersPresent = true
echo "Platform is ${TESTPLATFORM_OWNER}"
if (params.RedHatRemoteServer == null) { if (params.RedHatRemoteServer == null) {
allParametersPresent = false allParametersPresent = false
......
...@@ -44,7 +44,7 @@ function build_on_vm { ...@@ -44,7 +44,7 @@ function build_on_vm {
STATUS=1 STATUS=1
return return
fi fi
if [ ! -f /etc/apt/apt.conf.d/01proxy ] if [[ ! -f /etc/apt/apt.conf.d/01proxy ]] && [[ "$OPTIONAL_APTCACHER" != "true" ]]
then then
echo "Missing /etc/apt/apt.conf.d/01proxy file!" echo "Missing /etc/apt/apt.conf.d/01proxy file!"
echo "Is apt-cacher installed and configured?" echo "Is apt-cacher installed and configured?"
...@@ -96,12 +96,12 @@ function build_on_vm { ...@@ -96,12 +96,12 @@ function build_on_vm {
else else
scp -o StrictHostKeyChecking=no $JENKINS_WKSP/localZip.zip ubuntu@$VM_IP_ADDR:/home/ubuntu scp -o StrictHostKeyChecking=no $JENKINS_WKSP/localZip.zip ubuntu@$VM_IP_ADDR:/home/ubuntu
fi fi
scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$VM_IP_ADDR:/home/ubuntu [ -f /etc/apt/apt.conf.d/01proxy ] && scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$VM_IP_ADDR:/home/ubuntu
echo "############################################################" echo "############################################################"
echo "Running install and build script on VM ($VM_NAME)" echo "Running install and build script on VM ($VM_NAME)"
echo "############################################################" echo "############################################################"
echo "sudo cp 01proxy /etc/apt/apt.conf.d/" > $VM_CMDS echo "[ -f 01proxy ] && sudo cp 01proxy /etc/apt/apt.conf.d/" > $VM_CMDS
echo "touch /home/ubuntu/.hushlogin" >> $VM_CMDS echo "touch /home/ubuntu/.hushlogin" >> $VM_CMDS
if [[ "$VM_NAME" == *"-cppcheck"* ]] if [[ "$VM_NAME" == *"-cppcheck"* ]]
then then
......
...@@ -140,10 +140,25 @@ function command_options_usage { ...@@ -140,10 +140,25 @@ function command_options_usage {
echo "" echo ""
} }
# function to set specific behavior depending on the TESTPLATFORM_OWNER variable
# which may be set by a jenkins server for exemple
function platform_set {
if [ "$TESTPLATFORM_OWNER" != "" ]
then
echo "Running on $TESTPLATFORM_OWNER platform"
if [ -x "/usr/local/bin/oai_${TESTPLATFORM_OWNER}_setenv.sh" ]
then
. /usr/local/bin/oai_${TESTPLATFORM_OWNER}_setenv.sh
fi
fi
}
function setvar_usage { function setvar_usage {
declare -A HELP_VAR declare -A HELP_VAR
HELP_VAR["VM_OSREL"]="OS release to use in virtual machines" HELP_VAR["VM_OSREL"]="OS release to use in virtual machines"
HELP_VAR["RUN_EXPERIMENTAL"]="Enforce execution of variants with EXPERIMENTAL variable set to \"true\"" HELP_VAR["RUN_EXPERIMENTAL"]="Enforce execution of variants with EXPERIMENTAL variable set to \"true\""
HELP_VAR["OPTIONAL_APTCACHER"]="build and Run tests will fail if apt-cacher not installed and this variable not set to \"true\""
HELP_VAR["TESTPLATFORM_OWNER"]="Allow pipeline customization via execution of an externel scripts residing on the jenkins server"
echo "--setvar_<varname> <value> where varname is one of:" echo "--setvar_<varname> <value> where varname is one of:"
for i in ${AUTHORIZED_VAR[@]}; do printf "%20s : %s\n" "$i" "${HELP_VAR[$i]}" ;done for i in ${AUTHORIZED_VAR[@]}; do printf "%20s : %s\n" "$i" "${HELP_VAR[$i]}" ;done
} }
...@@ -315,6 +330,7 @@ function check_setvar { ...@@ -315,6 +330,7 @@ function check_setvar {
exit 1 exit 1
} }
platform_set
MY_DIR=$(dirname $(readlink -f $0)) MY_DIR=$(dirname $(readlink -f $0))
. $MY_DIR/createVM.sh . $MY_DIR/createVM.sh
. $MY_DIR/buildOnVM.sh . $MY_DIR/buildOnVM.sh
...@@ -324,6 +340,7 @@ MY_DIR=$(dirname $(readlink -f $0)) ...@@ -324,6 +340,7 @@ MY_DIR=$(dirname $(readlink -f $0))
. $MY_DIR/reportBuildLocally.sh . $MY_DIR/reportBuildLocally.sh
. $MY_DIR/reportTestLocally.sh . $MY_DIR/reportTestLocally.sh
if [ $# -lt 1 ] if [ $# -lt 1 ]
then then
echo "Syntax Error: too few arguments" echo "Syntax Error: too few arguments"
...@@ -440,7 +457,7 @@ RUN_OPTIONS="none" ...@@ -440,7 +457,7 @@ RUN_OPTIONS="none"
# list of variables that can be set via the --setvar option # list of variables that can be set via the --setvar option
AUTHORIZED_VAR=("VM_OSREL RUN_EXPERIMENTAL") AUTHORIZED_VAR=("VM_OSREL RUN_EXPERIMENTAL OPTIONAL_APTCACHER TESTPLATFORM_OWNER")
#variables to set which OS VM should use #variables to set which OS VM should use
......
...@@ -476,7 +476,7 @@ function install_epc_on_vm { ...@@ -476,7 +476,7 @@ function install_epc_on_vm {
local LOC_EPC_VM_IP_ADDR=`uvt-kvm ip $LOC_EPC_VM_NAME` local LOC_EPC_VM_IP_ADDR=`uvt-kvm ip $LOC_EPC_VM_NAME`
echo "$LOC_EPC_VM_NAME has for IP addr = $LOC_EPC_VM_IP_ADDR" echo "$LOC_EPC_VM_NAME has for IP addr = $LOC_EPC_VM_IP_ADDR"
scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$LOC_EPC_VM_IP_ADDR:/home/ubuntu [ -f /etc/apt/apt.conf.d/01proxy ] && scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$LOC_EPC_VM_IP_ADDR:/home/ubuntu
# ltebox specific actions (install and start) # ltebox specific actions (install and start)
LTE_BOX_TO_INSTALL=1 LTE_BOX_TO_INSTALL=1
...@@ -500,7 +500,7 @@ function install_epc_on_vm { ...@@ -500,7 +500,7 @@ function install_epc_on_vm {
echo "############################################################" echo "############################################################"
echo "Install EPC on EPC VM ($LOC_EPC_VM_NAME)" echo "Install EPC on EPC VM ($LOC_EPC_VM_NAME)"
echo "############################################################" echo "############################################################"
echo "sudo cp 01proxy /etc/apt/apt.conf.d/" > $LOC_EPC_VM_CMDS echo "sudo [ -f 01proxy ] && cp 01proxy /etc/apt/apt.conf.d/" > $LOC_EPC_VM_CMDS
echo "touch /home/ubuntu/.hushlogin" >> $LOC_EPC_VM_CMDS echo "touch /home/ubuntu/.hushlogin" >> $LOC_EPC_VM_CMDS
echo "echo \"sudo apt-get --yes --quiet install zip openjdk-8-jre libconfuse-dev libreadline-dev liblog4c-dev libgcrypt-dev libsctp-dev python2.7 python2.7-dev daemon iperf\"" >> $LOC_EPC_VM_CMDS echo "echo \"sudo apt-get --yes --quiet install zip openjdk-8-jre libconfuse-dev libreadline-dev liblog4c-dev libgcrypt-dev libsctp-dev python2.7 python2.7-dev daemon iperf\"" >> $LOC_EPC_VM_CMDS
echo "sudo apt-get update > zip-install.txt 2>&1" >> $LOC_EPC_VM_CMDS echo "sudo apt-get update > zip-install.txt 2>&1" >> $LOC_EPC_VM_CMDS
......
...@@ -1822,7 +1822,7 @@ add_library(LFDS7 ...@@ -1822,7 +1822,7 @@ add_library(LFDS7
# Simulation library # Simulation library
########################## ##########################
add_library(SIMU set (SIMUSRC
${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
...@@ -1833,9 +1833,13 @@ ${OPENAIR1_DIR}/SIMULATION/TOOLS/channel_sim.c ...@@ -1833,9 +1833,13 @@ ${OPENAIR1_DIR}/SIMULATION/TOOLS/channel_sim.c
${OPENAIR1_DIR}/SIMULATION/RF/rf.c ${OPENAIR1_DIR}/SIMULATION/RF/rf.c
${OPENAIR1_DIR}/SIMULATION/RF/dac.c ${OPENAIR1_DIR}/SIMULATION/RF/dac.c
${OPENAIR1_DIR}/SIMULATION/RF/adc.c ${OPENAIR1_DIR}/SIMULATION/RF/adc.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR_DIR}/targets/ARCH/rfsimulator/apply_channelmod.c
#${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
) )
# Simulation library
##########################
add_library( SIMU SHARED ${SIMUSRC} )
add_library(SIMU_ETH add_library(SIMU_ETH
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
...@@ -2134,7 +2138,6 @@ add_executable(lte-uesoftmodem ...@@ -2134,7 +2138,6 @@ add_executable(lte-uesoftmodem
${OPENAIR_TARGETS}/RT/USER/lte-ru.c ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
${OPENAIR_TARGETS}/RT/USER/ru_control.c ${OPENAIR_TARGETS}/RT/USER/ru_control.c
${OPENAIR_TARGETS}/RT/USER/rfsim.c ${OPENAIR_TARGETS}/RT/USER/rfsim.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR2_DIR}/RRC/NAS/nas_config.c ${OPENAIR2_DIR}/RRC/NAS/nas_config.c
......
...@@ -150,7 +150,7 @@ Options ...@@ -150,7 +150,7 @@ Options
--build-eclipse --build-eclipse
Build eclipse project files. Paths are auto corrected by fixprj.sh Build eclipse project files. Paths are auto corrected by fixprj.sh
--build-lib <libraries> --build-lib <libraries>
Build optional shared library, <libraries> can be one or several of $OPTIONAL_LIBRARIES Build optional shared library, <libraries> can be one or several of $OPTIONAL_LIBRARIES or \"all\"
--usrp-recplay --usrp-recplay
Build for I/Q record-playback modes Build for I/Q record-playback modes
...@@ -324,6 +324,10 @@ function main() { ...@@ -324,6 +324,10 @@ function main() {
shift 1;; shift 1;;
--build-lib) --build-lib)
BUILD_OPTLIB="" BUILD_OPTLIB=""
if [ "$2" == "all" ] ; then
BUILD_OPTLIB="$OPTIONAL_LIBRARIES"
echo_info "Enabling build of all optional shared libraries ($OPTIONAL_LIBRARIES)"
else
for alib in $2 ; do for alib in $2 ; do
for oklib in $OPTIONAL_LIBRARIES ; do for oklib in $OPTIONAL_LIBRARIES ; do
if [ "$alib" = "$oklib" ] ; then if [ "$alib" = "$oklib" ] ; then
...@@ -335,6 +339,7 @@ function main() { ...@@ -335,6 +339,7 @@ function main() {
if [ "${BUILD_OPTLIB## }" != "$2" ] ; then if [ "${BUILD_OPTLIB## }" != "$2" ] ; then
echo_fatal "Unknown optional library in $2, valid libraries are $OPTIONAL_LIBRARIES" echo_fatal "Unknown optional library in $2, valid libraries are $OPTIONAL_LIBRARIES"
fi fi
fi
shift 2;; shift 2;;
--usrp-recplay) --usrp-recplay)
USRP_REC_PLAY="True" USRP_REC_PLAY="True"
...@@ -515,21 +520,7 @@ function main() { ...@@ -515,21 +520,7 @@ function main() {
$lte_build_dir $lte_exec \ $lte_build_dir $lte_exec \
$lte_exec $dbin/$lte_exec.$REL $lte_exec $dbin/$lte_exec.$REL
# mandatory shared lib
compilations \
$lte_build_dir $config_libconfig_shlib \
lib$config_libconfig_shlib.so $dbin/lib$config_libconfig_shlib.so
compilations \
$lte_build_dir coding \
libcoding.so $dbin/libcoding.so
# optional libs (used when noS1 with kernel modules
compilations \
$lte_build_dir nasmesh \
CMakeFiles/nasmesh/nasmesh.ko $dbin/nasmesh.ko
compilations \
$lte_build_dir rb_tool \
rb_tool $dbin/rb_tool
cp $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $dbin
fi fi
if [ "$UE" = 1 ] ; then if [ "$UE" = 1 ] ; then
...@@ -538,21 +529,6 @@ function main() { ...@@ -538,21 +529,6 @@ function main() {
$lte_build_dir $lte_exec \ $lte_build_dir $lte_exec \
$lte_exec $dbin/$lte_exec.$REL $lte_exec $dbin/$lte_exec.$REL
# mandatory shared lib
compilations \
$lte_build_dir $config_libconfig_shlib \
lib$config_libconfig_shlib.so $dbin/lib$config_libconfig_shlib.so
compilations \
$lte_build_dir coding \
libcoding.so $dbin/libcoding.so
# optional libs (used when noS1 with kernel modules
compilations \
$lte_build_dir nasmesh \
CMakeFiles/nasmesh/nasmesh.ko $dbin/nasmesh.ko
compilations \
$lte_build_dir rb_tool \
rb_tool $dbin/rb_tool
cp $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $dbin
# ue_ip driver compilation # ue_ip driver compilation
compilations \ compilations \
$lte_build_dir ue_ip \ $lte_build_dir ue_ip \
...@@ -665,10 +641,25 @@ function main() { ...@@ -665,10 +641,25 @@ function main() {
fi fi
# build RF device and transport protocol libraries # build RF device, transport protocol libraries and all
# shared libraries common to UE and eNB
##################################### #####################################
if [ "$eNB" = "1" -o "$UE" = "1" ] ; then if [ "$eNB" = "1" -o "$UE" = "1" ] ; then
# mandatory shared lib
compilations \
$lte_build_dir $config_libconfig_shlib \
lib$config_libconfig_shlib.so $dbin/lib$config_libconfig_shlib.so
compilations \
$lte_build_dir coding \
libcoding.so $dbin/libcoding.so
# optional libs (used when noS1 with kernel modules
compilations \
$lte_build_dir nasmesh \
CMakeFiles/nasmesh/nasmesh.ko $dbin/nasmesh.ko
compilations \
$lte_build_dir rb_tool \
rb_tool $dbin/rb_tool
cp $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $dbin
# build RF device libraries # build RF device libraries
if [ "$HW" != "None" ] ; then if [ "$HW" != "None" ] ; then
rm -f liboai_device.so rm -f liboai_device.so
...@@ -737,7 +728,7 @@ function main() { ...@@ -737,7 +728,7 @@ function main() {
echo_info "liboai_transpro.so is linked to ETHERNET transport" echo_info "liboai_transpro.so is linked to ETHERNET transport"
fi fi
if [ "$RFSIMULATOR" == "true" -o "$HW" == "OAI_SIMU" ] ; then if [ "$HW" == "OAI_SIMU" ] ; then
echo_info "Compiling rfsimulator" echo_info "Compiling rfsimulator"
compilations \ compilations \
$lte_build_dir rfsimulator \ $lte_build_dir rfsimulator \
......
## config module management
```c ```c
configmodule_interface_t *load_configmodule(int argc, char **argv, uint32_t initflags) configmodule_interface_t *load_configmodule(int argc, char **argv, uint32_t initflags)
``` ```
...@@ -14,23 +16,17 @@ void End_configmodule(void) ...@@ -14,23 +16,17 @@ void End_configmodule(void)
* Free memory which has been allocated by the configuration module since its initialization. * Free memory which has been allocated by the configuration module since its initialization.
* Possibly calls the `config_<config source>_end` function * Possibly calls the `config_<config source>_end` function
## Retrieving parameter's values
```c ```c
int config_get(paramdef_t *params,int numparams, char *prefix) int config_get(paramdef_t *params,int numparams, char *prefix)
``` ```
* Reads as many parameters as described in params, they must all be in the same configuration file section * Reads as many parameters as described in params, they must all be in the same configuration file section
* Calls the `config_<config source>_get` function * Calls the `config_<config source>_get` function
* Calls the `config_process_cmdline` function * Calls the `config_process_cmdline` function
* `params` points to an array of `paramdef_t` structures which describes the parameters to be read, possibly including a pointer to a checking function. The following bits can possibly be set in the `paramflags` mask before calling * `params` points to an array of `paramdef_t` structures which describes the parameters to be read, possibly including a pointer to a checking function.The `paramflags` bit mask can be used to modify how a specific parameter is processed and the same mask is also used by the configuration module to return information about how the parameter has been processed. Bits definitions are described in the [`paramdef_t` structure description](./struct.md)
- `PARAMFLAG_MANDATORY`: -1 is returned if the parameter is not explicitly defined in the config source.
- `PARAMFLAG_DISABLECMDLINE`: parameter cannot be modified via the command line
- `PARAMFLAG_DONOTREAD`: ignore the parameter, can be used at run-time, to alter a pre-defined `paramdef_t` array which is used in several `config_get` or/and `config_getlist` calls.
- `PARAMFLAG_NOFREE`: do not free the memory possibly allocated by the config module to store the value of the parameter. Default behavior is for the config module to free the memory it has allocated when the `config_end` function is called.
- `PARAMFLAG_BOOL`: Only relevant for integer types. tell the config module that when processing the command line, the corresponding option can be specified without any arggument and that in this case it must set the value to 1.
* `params` is also used as an output parameter, `< XXX >ptr >` field is used by the config module to store the value it has read. The following bits can possibly be set in the `paramflags` mask after the call:
- `PARAMFLAG_MALLOCINCONFIG`: memory has been allocated for the ` < XXX >ptr > ` field
- `PARAMFLAG_PARAMSET`: parameter has been found in the config source, it is not set to default value.
- `PARAMFLAG_PARAMSET`: parameter has been set to its default value
* `numparams` is the number of entries in the params array * `numparams` is the number of entries in the params array
* `prefix` is a character string to be appended to the parameters name, it defines the parameters position in the configuration file hierarchy (the section name in libconfig terminology). * `prefix` is a character string to be appended to the parameters name, it defines the parameters position in the configuration file hierarchy (the section name in libconfig terminology).
* The returned value is the number of parameters which have been assigned a value or -1 if a severe error occured * The returned value is the number of parameters which have been assigned a value or -1 if a severe error occured
...@@ -44,6 +40,9 @@ int config_libconfig_getlist(paramlist_def_t *ParamList, paramdef_t *params, int ...@@ -44,6 +40,9 @@ int config_libconfig_getlist(paramlist_def_t *ParamList, paramdef_t *params, int
* `ParamList` points to a structure, where `paramarray` field points to an array of `paramdef_t` structure, allocated by the function. It is used to return the values of the parameters. * `ParamList` points to a structure, where `paramarray` field points to an array of `paramdef_t` structure, allocated by the function. It is used to return the values of the parameters.
* The returned value is the number of occurrences in the list or -1 in case of severe error * The returned value is the number of occurrences in the list or -1 in case of severe error
## utility functions and macros
The configuration module also defines APIs to access the `paramdef_t` and `configmodule_interface_t` fields. They are listed in the configuration module [include file `common/config/config_userapi.h`](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_userapi.h)
[Configuration module developer main page](../../config/devusage.md) [Configuration module developer main page](../../config/devusage.md)
[Configuration module home](../../config.md) [Configuration module home](../../config.md)
...@@ -5,6 +5,7 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla ...@@ -5,6 +5,7 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla
|:-----------|:------------------------------------------------------------------|----:| |:-----------|:------------------------------------------------------------------|----:|
| `optname` | parameter name, as used when looking for it in the config source, 63 bytes max (64 with trailing \0) | I | | `optname` | parameter name, as used when looking for it in the config source, 63 bytes max (64 with trailing \0) | I |
| `helstr` | pointer to a C string printed when using --help on the command line | I | | `helstr` | pointer to a C string printed when using --help on the command line | I |
| `paramflags` | bit mask, used to modify how the parameter is processed, or to return to the API caller how the parameter has been set, see list in the next table | IO |
| `strptr` `strlistptr` `u8ptr` `i8ptr` `u16ptr` `i16ptr` `uptr` `iptr` `u64ptr` `i64ptr` `dblptr` `voidptr` | a pointer to a variable where the parameter value(s) will be returned. This field is an anonymous union, the supported pointer types have been built to avoid type mismatch warnings at compile time. | O | | `strptr` `strlistptr` `u8ptr` `i8ptr` `u16ptr` `i16ptr` `uptr` `iptr` `u64ptr` `i64ptr` `dblptr` `voidptr` | a pointer to a variable where the parameter value(s) will be returned. This field is an anonymous union, the supported pointer types have been built to avoid type mismatch warnings at compile time. | O |
| `defstrval` `defstrlistval` `defuintval` `defintval` `defint64val` `defintarrayval` `defdblval` | this field is an anonymous union, it can be used to define the default value for the parameter. It is ignored if `PARAMFLAG_MANDATORY` is set in the `paramflags` field.| I | | `defstrval` `defstrlistval` `defuintval` `defintval` `defint64val` `defintarrayval` `defdblval` | this field is an anonymous union, it can be used to define the default value for the parameter. It is ignored if `PARAMFLAG_MANDATORY` is set in the `paramflags` field.| I |
| `type` | Supported parameter types are defined as integer macros. Supported simple types are `TYPE_STRING`, parameter value is returned in `strptr` field, `TYPE_INT8` `TYPE_UINT8` `TYPE_INT16` `TYPE_UINT16` `TYPE_INT32` `TYPE_UINT32` `TYPE_INT64` `TYPE_UINT64`, parameter value is returned in the corresponding uXptr or iXptr, `TYPE_MASK`, value is returned in `u32ptr`, `TYPE_DOUBLE` value is returned in `dblptr`, `TYPE_IPV4ADDR` value is returned in binary, network bytes order in `u32ptr` field. `TYPE_STRINGLIST`, `TYPE_INTARRAY` and `TYPE_UINTARRAY` are multiple values types. Multiple values are returned in respectively, `strlistptr`, `iptr` and `uptr` fields which then point to arrays. The `numelt` field gives the number of item in the array. | I | | `type` | Supported parameter types are defined as integer macros. Supported simple types are `TYPE_STRING`, parameter value is returned in `strptr` field, `TYPE_INT8` `TYPE_UINT8` `TYPE_INT16` `TYPE_UINT16` `TYPE_INT32` `TYPE_UINT32` `TYPE_INT64` `TYPE_UINT64`, parameter value is returned in the corresponding uXptr or iXptr, `TYPE_MASK`, value is returned in `u32ptr`, `TYPE_DOUBLE` value is returned in `dblptr`, `TYPE_IPV4ADDR` value is returned in binary, network bytes order in `u32ptr` field. `TYPE_STRINGLIST`, `TYPE_INTARRAY` and `TYPE_UINTARRAY` are multiple values types. Multiple values are returned in respectively, `strlistptr`, `iptr` and `uptr` fields which then point to arrays. The `numelt` field gives the number of item in the array. | I |
...@@ -12,6 +13,22 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla ...@@ -12,6 +13,22 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla
| `chkPptr` | possible pointer to the structure containing the info used to check parameter values | I | | `chkPptr` | possible pointer to the structure containing the info used to check parameter values | I |
| `processedvalue` | When `chkPptr` is not `ǸULL`, is used to return a value, computed from the original parameter, as read from the configuration source. | O | | `processedvalue` | When `chkPptr` is not `ǸULL`, is used to return a value, computed from the original parameter, as read from the configuration source. | O |
## `paramflags` bits definition
| C macro bit definition | usage | I/O |
|:-------------------------------------|:---------------------------------------------------------------------------------------------------------------------|----:|
| `PARAMFLAG_MANDATORY` | parameter is mandatory, comfiguration module will stop the process if it is not specified. Default value is ignored | I |
| `PARAMFLAG_DISABLECMDLINE` | parameter cannot be specified on the command line | I |
| `PARAMFLAG_DONOTREAD` | ignore the parameter, usefull when a parameter group is used in different context | I |
| `PARAMFLAG_NOFREE` | The end_configmodule API won't free the memory which has been possibly allocated to store the value of the parameter.| I |
| `PARAMFLAG_BOOL` | Parameter is a boolean, it can be specified without a value to set it to true | I |
| `PARAMFLAG_CMDLINE_NOPREFIXENABLED` | parameter can be specified without the prefix on the command line. Must be used with care, carefuly checking unicity, especially for short parameter names | I |
| `PARAMFLAG_MALLOCINCONFIG` | Memory for the parameter value has been allocated by the configuration module |O |
| `PARAMFLAG_PARAMSET` | Parameter value has been explicitely set, as the parameter was specified either on the command line or the config source | O |
| `PARAMFLAG_PARAMSETDEF` | Parameter value has been set to it's default | O |
# `paramlist_def_t`structure # `paramlist_def_t`structure
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L160). It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L160).
It is used as an argument to `config_getlist` calls, to get values of multiple occurrences of group of parameters. It is used as an argument to `config_getlist` calls, to get values of multiple occurrences of group of parameters.
......
...@@ -167,8 +167,8 @@ int config_check_unknown_cmdlineopt(char *prefix) { ...@@ -167,8 +167,8 @@ int config_check_unknown_cmdlineopt(char *prefix) {
char testprefix[CONFIG_MAXOPTLENGTH]; char testprefix[CONFIG_MAXOPTLENGTH];
int finalcheck = 0; int finalcheck = 0;
memset(testprefix,0,sizeof(testprefix)); memset(testprefix,0,sizeof(testprefix));
memset(testprefix,0,sizeof(testprefix)); memset(testprefix,0,sizeof(testprefix));
if (prefix != NULL) { if (prefix != NULL) {
if (strcmp(prefix,CONFIG_CHECKALLSECTIONS) == 0) if (strcmp(prefix,CONFIG_CHECKALLSECTIONS) == 0)
finalcheck = 1; finalcheck = 1;
...@@ -253,7 +253,9 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix) ...@@ -253,7 +253,9 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix)
} }
if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */ if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) ) { ((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) || /* long option beginning with "--" */
((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgoptions[n].optname) == 0) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ||
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 ) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ) {
char *valptr=NULL; char *valptr=NULL;
int ret; int ret;
config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED;
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define PARAMFLAG_DONOTREAD (1 << 2) // parameter must be ignored in get function #define PARAMFLAG_DONOTREAD (1 << 2) // parameter must be ignored in get function
#define PARAMFLAG_NOFREE (1 << 3) // don't free parameter in end function #define PARAMFLAG_NOFREE (1 << 3) // don't free parameter in end function
#define PARAMFLAG_BOOL (1 << 4) // integer param can be 0 or 1 #define PARAMFLAG_BOOL (1 << 4) // integer param can be 0 or 1
#define PARAMFLAG_CMDLINE_NOPREFIXENABLED (1 << 5) // on the command line, allow a parameter to be specified without the prefix
/* Flags used by config modules to return info to calling modules and/or to for internal usage*/ /* Flags used by config modules to return info to calling modules and/or to for internal usage*/
#define PARAMFLAG_MALLOCINCONFIG (1 << 15) // parameter allocated in config module #define PARAMFLAG_MALLOCINCONFIG (1 << 15) // parameter allocated in config module
......
...@@ -172,7 +172,7 @@ int config_get_processedint(paramdef_t *cfgoption) { ...@@ -172,7 +172,7 @@ int config_get_processedint(paramdef_t *cfgoption) {
return ret; return ret;
} }
void config_printhelp(paramdef_t *params,int numparams, char *prefix) { void config_printhelp(paramdef_t *params,int numparams, char *prefix) {
printf("\n-----Help for section %-26s: %03i entries------\n",(prefix==NULL)?"(root section)":prefix ,numparams); printf("\n-----Help for section %-26s: %03i entries------\n",(prefix==NULL)?"(root section)":prefix,numparams);
for (int i=0 ; i<numparams ; i++) { for (int i=0 ; i<numparams ; i++) {
printf(" %s%s: %s", printf(" %s%s: %s",
...@@ -204,6 +204,16 @@ int config_execcheck(paramdef_t *params,int numparams, char *prefix) { ...@@ -204,6 +204,16 @@ int config_execcheck(paramdef_t *params,int numparams, char *prefix) {
return st; return st;
} }
int config_paramidx_fromname(paramdef_t *params,int numparams, char *name) {
for (int i=0; i<numparams ; i++) {
if (strcmp(name,params[i].optname) == 0)
return i;
}
fprintf(stderr,"[CONFIG]config_paramidx_fromname , %s is not a valid parameter name\n",name);
return -1;
}
int config_get(paramdef_t *params,int numparams, char *prefix) { int config_get(paramdef_t *params,int numparams, char *prefix) {
int ret= -1; int ret= -1;
...@@ -438,7 +448,7 @@ int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix) { ...@@ -438,7 +448,7 @@ int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix) {
status=1; status=1;
for (int j=0; j<cfgoptions->numelt ; j++) { for (int j=0; j<cfgoptions->numelt ; j++) {
printf_params("[CONFIG] %s[%i] set to default value %i\n",cfgoptions->optname ,j,(int)cfgoptions->iptr[j]); printf_params("[CONFIG] %s[%i] set to default value %i\n",cfgoptions->optname,j,(int)cfgoptions->iptr[j]);
} }
} }
...@@ -452,7 +462,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { ...@@ -452,7 +462,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) {
if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) { if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) {
*(cfgoptions->dblptr)=cfgoptions->defdblval; *(cfgoptions->dblptr)=cfgoptions->defdblval;
status=1; status=1;
printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname , *(cfgoptions->dblptr)); printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname, *(cfgoptions->dblptr));
} }
return status; return status;
...@@ -460,7 +470,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { ...@@ -460,7 +470,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) {
int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr) { int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr) {
config_check_valptr(cfgoptions,(char **)&(cfgoptions->uptr), sizeof(int)); config_check_valptr(cfgoptions,(char **)&(cfgoptions->uptr), sizeof(int));
int rst=inet_pton(AF_INET, ipv4addr ,cfgoptions->uptr ); int rst=inet_pton(AF_INET, ipv4addr,cfgoptions->uptr );
if (rst == 1 && *(cfgoptions->uptr) > 0) { if (rst == 1 && *(cfgoptions->uptr) > 0) {
printf_params("[CONFIG] %s: %s\n",cfgoptions->optname, ipv4addr); printf_params("[CONFIG] %s: %s\n",cfgoptions->optname, ipv4addr);
......
...@@ -39,6 +39,7 @@ extern "C" ...@@ -39,6 +39,7 @@ extern "C"
{ {
#endif #endif
/* utility functions to ease usage of config module structures */
#define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode ) #define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode )
#define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP ) #define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP )
#define CONFIG_GETP(P) ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgP[P] ) #define CONFIG_GETP(P) ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgP[P] )
...@@ -46,6 +47,8 @@ extern "C" ...@@ -46,6 +47,8 @@ extern "C"
#define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= P; } #define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= P; }
#define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); } #define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); }
#define CONFIG_ISPARAMFLAGSET(P,F) ( !!(P.paramflags & F)) #define CONFIG_ISPARAMFLAGSET(P,F) ( !!(P.paramflags & F))
extern int config_paramidx_fromname(paramdef_t *params,int numparams, char *name);
/* utility functions, to be used by configuration module and/or configuration libraries */ /* utility functions, to be used by configuration module and/or configuration libraries */
extern configmodule_interface_t *config_get_if(void); extern configmodule_interface_t *config_get_if(void);
extern char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) ; extern char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) ;
......
...@@ -123,7 +123,7 @@ void client_printf(const char *message, ...) { ...@@ -123,7 +123,7 @@ void client_printf(const char *message, ...) {
if (telnetparams.new_socket > 0) { if (telnetparams.new_socket > 0) {
vsnprintf(telnetparams.msgbuff,sizeof(telnetparams.msgbuff)-1,message, va_args); vsnprintf(telnetparams.msgbuff,sizeof(telnetparams.msgbuff)-1,message, va_args);
send(telnetparams.new_socket,telnetparams.msgbuff , strlen(telnetparams.msgbuff), MSG_NOSIGNAL); send(telnetparams.new_socket,telnetparams.msgbuff, strlen(telnetparams.msgbuff), MSG_NOSIGNAL);
} else { } else {
vprintf(message, va_args); vprintf(message, va_args);
} }
...@@ -475,7 +475,7 @@ int process_command(char *buf) { ...@@ -475,7 +475,7 @@ int process_command(char *buf) {
memset(cmdb,0,sizeof(cmdb)); memset(cmdb,0,sizeof(cmdb));
bufbck=strdup(buf); bufbck=strdup(buf);
rt=CMDSTATUS_NOTFOUND; rt=CMDSTATUS_NOTFOUND;
j = sscanf(buf,"%9s %9s %9[^\t\n]",modulename,cmd,cmdb); j = sscanf(buf,"%19s %19s %19[^\t\n]",modulename,cmd,cmdb);
if (telnetparams.telnetdbg > 0) if (telnetparams.telnetdbg > 0)
printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb); printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb);
...@@ -543,7 +543,7 @@ void run_telnetsrv(void) { ...@@ -543,7 +543,7 @@ void run_telnetsrv(void) {
char buf[TELNET_MAX_MSGLENGTH]; char buf[TELNET_MAX_MSGLENGTH];
struct sockaddr cli_addr; struct sockaddr cli_addr;
unsigned int cli_len = sizeof(cli_addr); unsigned int cli_len = sizeof(cli_addr);
int readc , filled; int readc, filled;
int status; int status;
int optval = 1; int optval = 1;
pthread_setname_np(pthread_self(), "telnet"); pthread_setname_np(pthread_self(), "telnet");
...@@ -604,7 +604,7 @@ void run_telnetsrv(void) { ...@@ -604,7 +604,7 @@ void run_telnetsrv(void) {
} }
if (telnetparams.telnetdbg > 0) if (telnetparams.telnetdbg > 0)
printf("[TELNETSRV] Command received: readc %i filled %i \"%s\"\n", readc, filled ,buf); printf("[TELNETSRV] Command received: readc %i filled %i \"%s\"\n", readc, filled,buf);
if (buf[0] == '!') { if (buf[0] == '!') {
if (buf[1] == '!') { if (buf[1] == '!') {
......
...@@ -54,7 +54,7 @@ cd cmake_targets/ ...@@ -54,7 +54,7 @@ cd cmake_targets/
``` ```
- The `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. - The `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed.
- The `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one,`liboai_usrpdevif.so` . USRP is the only hardware tested today in the Continuous Integration process. - The `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one,`liboai_usrpdevif.so` . USRP is the only hardware tested today in the Continuous Integration process. The RF simulator[RF simulator](../targets/ARCH/rfsimulator/README.md) is implemented as a specific device replacing RF hardware, it can be build using `-w SIMU` option.
- `--eNB` is to build the `lte-softmodem` executable and all required shared libraries - `--eNB` is to build the `lte-softmodem` executable and all required shared libraries
- `--UE` is to build the `lte-uesoftmodem` executable and all required shared libraries - `--UE` is to build the `lte-uesoftmodem` executable and all required shared libraries
......
...@@ -122,7 +122,6 @@ void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxt ...@@ -122,7 +122,6 @@ void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxt
phich->config[phich->num_hi].n_DMRS = hi_dci0_config_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms; phich->config[phich->num_hi].n_DMRS = hi_dci0_config_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms;
phich->num_hi++; phich->num_hi++;
AssertFatal(phich->num_hi<32,"Maximum number of phich reached in subframe\n"); AssertFatal(phich->num_hi<32,"Maximum number of phich reached in subframe\n");
} }
void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,
...@@ -186,6 +185,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro ...@@ -186,6 +185,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro
#endif #endif
harq_pid = dlsch0->harq_ids[proc->frame_tx%2][proc->subframe_tx]; harq_pid = dlsch0->harq_ids[proc->frame_tx%2][proc->subframe_tx];
if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) { if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
return; return;
...@@ -260,9 +260,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro ...@@ -260,9 +260,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro
dlsch0->harq_mask = 1; dlsch0->harq_mask = 1;
dlsch0_harq = dlsch0->harq_processes[0]; dlsch0_harq = dlsch0->harq_processes[0];
dlsch0_harq->pdu = sdu; dlsch0_harq->pdu = sdu;
LOG_D(PHY,"NFAPI: frame %d, subframe %d (TX %d.%d): Programming SI-BR (%d) => %d\n",frame,subframe,proc->frame_tx,proc->subframe_tx,rel13->pdsch_payload_type,UE_id); LOG_D(PHY,"NFAPI: frame %d, subframe %d (TX %d.%d): Programming SI-BR (%d) => %d\n",frame,subframe,proc->frame_tx,proc->subframe_tx,rel13->pdsch_payload_type,UE_id);
dlsch0->rnti = 0xFFFF; dlsch0->rnti = 0xFFFF;
dlsch0->Kmimo = 1; dlsch0->Kmimo = 1;
dlsch0->Mdlharq = 4; dlsch0->Mdlharq = 4;
...@@ -569,8 +567,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB, ...@@ -569,8 +567,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB,
nfapi_ul_config_request_pdu_t *ul_config_pdu, nfapi_ul_config_request_pdu_t *ul_config_pdu,
uint16_t frame, uint16_t frame,
uint8_t subframe, uint8_t subframe,
uint8_t srs_active) uint8_t srs_active) {
{
LTE_eNB_UCI *uci = &eNB->uci_vars[UE_id]; LTE_eNB_UCI *uci = &eNB->uci_vars[UE_id];
if (NFAPI_MODE==NFAPI_MODE_VNF) return; if (NFAPI_MODE==NFAPI_MODE_VNF) return;
...@@ -820,6 +817,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -820,6 +817,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
if (NFAPI_MODE!=NFAPI_MODE_VNF) if (NFAPI_MODE!=NFAPI_MODE_VNF)
handle_nfapi_dci_dl_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu); handle_nfapi_dci_dl_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu);
eNB->pdcch_vars[NFAPI_SFNSF2SF(DL_req->sfn_sf)&1].num_dci++; eNB->pdcch_vars[NFAPI_SFNSF2SF(DL_req->sfn_sf)&1].num_dci++;
//LOG_E(PHY,"Incremented num_dci:%d but already set??? dl_config:num_dci:%d\n", eNB->pdcch_vars[subframe&1].num_dci, number_dci); //LOG_E(PHY,"Incremented num_dci:%d but already set??? dl_config:num_dci:%d\n", eNB->pdcch_vars[subframe&1].num_dci, number_dci);
do_oai=1; do_oai=1;
...@@ -832,11 +830,13 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -832,11 +830,13 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
TX_req->tx_request_body.number_of_pdus); TX_req->tx_request_body.number_of_pdus);
eNB->pbch_configured=1; eNB->pbch_configured=1;
do_oai=1; do_oai=1;
//LOG_D(PHY,"%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE TX:%d/%d RX:%d/%d TXREQ:%d/%d\n", //LOG_D(PHY,"%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE TX:%d/%d RX:%d/%d TXREQ:%d/%d\n",
//__FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2SFN(TX_req->sfn_sf), NFAPI_SFNSF2SF(TX_req->sfn_sf)); //__FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2SFN(TX_req->sfn_sf), NFAPI_SFNSF2SF(TX_req->sfn_sf));
if (NFAPI_MODE!=NFAPI_MODE_VNF) if (NFAPI_MODE!=NFAPI_MODE_VNF)
handle_nfapi_bch_pdu(eNB,proc,dl_config_pdu, handle_nfapi_bch_pdu(eNB,proc,dl_config_pdu,
TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index].segments[0].segment_data); TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index].segments[0].segment_data);
break; break;
case NFAPI_DL_CONFIG_MCH_PDU_TYPE: case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
...@@ -911,6 +911,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -911,6 +911,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
if (NFAPI_MODE!=NFAPI_MODE_VNF) if (NFAPI_MODE!=NFAPI_MODE_VNF)
handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu); handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu);
eNB->mpdcch_vars[subframe&1].num_dci++; eNB->mpdcch_vars[subframe&1].num_dci++;
break; break;
#endif #endif
...@@ -918,10 +919,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -918,10 +919,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
} }
if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && do_oai && !dont_send) { if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && do_oai && !dont_send) {
if(Sched_INFO->TX_req->tx_request_body.number_of_pdus > 0){ if(Sched_INFO->TX_req->tx_request_body.number_of_pdus > 0) {
Sched_INFO->TX_req->sfn_sf = frame << 4 | subframe; Sched_INFO->TX_req->sfn_sf = frame << 4 | subframe;
oai_nfapi_tx_req(Sched_INFO->TX_req); oai_nfapi_tx_req(Sched_INFO->TX_req);
} }
Sched_INFO->DL_req->sfn_sf = frame << 4 | subframe; Sched_INFO->DL_req->sfn_sf = frame << 4 | subframe;
oai_nfapi_dl_config_req(Sched_INFO->DL_req); // DJP - .dl_config_request_body.dl_config_pdu_list[0]); // DJP - FIXME TODO - yuk - only copes with 1 pdu oai_nfapi_dl_config_req(Sched_INFO->DL_req); // DJP - .dl_config_request_body.dl_config_pdu_list[0]); // DJP - FIXME TODO - yuk - only copes with 1 pdu
Sched_INFO->UE_release_req->sfn_sf = frame << 4 | subframe; Sched_INFO->UE_release_req->sfn_sf = frame << 4 | subframe;
...@@ -935,7 +937,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { ...@@ -935,7 +937,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_pdcch_symbols=0; eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_pdcch_symbols=0;
} }
if (NFAPI_MODE!=NFAPI_MODE_VNF) if (NFAPI_MODE!=NFAPI_MODE_VNF)
for (i=0; i<number_hi_dci0_pdu; i++) { for (i=0; i<number_hi_dci0_pdu; i++) {
hi_dci0_req_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[i]; hi_dci0_req_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[i];
LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type); LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type);
......
...@@ -30,11 +30,32 @@ ...@@ -30,11 +30,32 @@
#include "sim.h" #include "sim.h"
#include "scm_corrmat.h" #include "scm_corrmat.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "common/config/config_userapi.h"
#include "common/utils/telnetsrv/telnetsrv.h"
#include "common/utils/load_module_shlib.h"
//#define DEBUG_CH //#define DEBUG_CH
#include "assertions.h" #include "assertions.h"
extern void print_shorts(char *s,__m128i *x); extern void print_shorts(char *s,__m128i *x);
static mapping channelmod_names[] = {
CHANNELMOD_MAP_INIT
};
static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt);
static telnetshell_cmddef_t channelmod_cmdarray[] = {
{"show","",channelmod_show_cmd},
{"","",NULL},
};
static telnetshell_vardef_t channelmod_vardef[] = {
{"",0,NULL}
};
static double snr_dB=25;
static double sinr_dB=0;
void fill_channel_desc(channel_desc_t *chan_desc, void fill_channel_desc(channel_desc_t *chan_desc,
uint8_t nb_tx, uint8_t nb_tx,
...@@ -43,7 +64,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -43,7 +64,7 @@ void fill_channel_desc(channel_desc_t *chan_desc,
uint8_t channel_length, uint8_t channel_length,
double *amps, double *amps,
double *delays, double *delays,
struct complex** R_sqrt, struct complex **R_sqrt,
double Td, double Td,
double sampling_rate, double sampling_rate,
double channel_bandwidth, double channel_bandwidth,
...@@ -53,30 +74,27 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -53,30 +74,27 @@ void fill_channel_desc(channel_desc_t *chan_desc,
double max_Doppler, double max_Doppler,
int32_t channel_offset, int32_t channel_offset,
double path_loss_dB, double path_loss_dB,
uint8_t random_aoa) uint8_t random_aoa) {
{
uint16_t i,j; uint16_t i,j;
double delta_tau; double delta_tau;
LOG_I(OCM,"[CHANNEL] Getting new channel descriptor, nb_tx %d, nb_rx %d, nb_taps %d, channel_length %d\n", 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_tx = nb_tx;
chan_desc->nb_rx = nb_rx; chan_desc->nb_rx = nb_rx;
chan_desc->nb_taps = nb_taps; chan_desc->nb_taps = nb_taps;
chan_desc->channel_length = channel_length; chan_desc->channel_length = channel_length;
chan_desc->amps = amps; chan_desc->amps = amps;
LOG_D(OCM,"[CHANNEL] Doing delays ...\n"); LOG_D(OCM,"[CHANNEL] Doing delays ...\n");
if (delays==NULL) { if (delays==NULL) {
chan_desc->delays = (double*) malloc(nb_taps*sizeof(double)); chan_desc->delays = (double *) malloc(nb_taps*sizeof(double));
delta_tau = Td/nb_taps; delta_tau = Td/nb_taps;
for (i=0; i<nb_taps; i++) for (i=0; i<nb_taps; i++)
chan_desc->delays[i] = ((double)i)*delta_tau; chan_desc->delays[i] = ((double)i)*delta_tau;
} } else
else
chan_desc->delays = delays; chan_desc->delays = delays;
chan_desc->Td = Td; chan_desc->Td = Td;
chan_desc->sampling_rate = sampling_rate; chan_desc->sampling_rate = sampling_rate;
chan_desc->channel_bandwidth = channel_bandwidth; chan_desc->channel_bandwidth = channel_bandwidth;
...@@ -89,37 +107,40 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -89,37 +107,40 @@ void fill_channel_desc(channel_desc_t *chan_desc,
chan_desc->first_run = 1; chan_desc->first_run = 1;
chan_desc->ip = 0.0; chan_desc->ip = 0.0;
chan_desc->max_Doppler = max_Doppler; chan_desc->max_Doppler = max_Doppler;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(nb_taps*sizeof(struct complex*)); chan_desc->a = (struct complex **) malloc(nb_taps*sizeof(struct complex *));
LOG_D(OCM,"[CHANNEL] Filling ch \n"); LOG_D(OCM,"[CHANNEL] Filling ch \n");
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); // allocate for up to 100 RBs, 12 samples per RB 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); LOG_D(OCM,"[CHANNEL] Filling a (nb_taps %d)\n",nb_taps);
for (i = 0; i<nb_taps; i++) { for (i = 0; i<nb_taps; i++) {
LOG_D(OCM,"tap %d (%p,%zu)\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)); chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
} }
LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n"); LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n");
if (R_sqrt == NULL) { 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++) { 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.0; chan_desc->R_sqrt[i][j].y = 0.0;
} }
} }
} } else {
else { 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++) { 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));
//chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0];
...@@ -135,16 +156,15 @@ void fill_channel_desc(channel_desc_t *chan_desc, ...@@ -135,16 +156,15 @@ void fill_channel_desc(channel_desc_t *chan_desc,
} }
LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor); 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]); 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; chan_desc->nb_paths=10;
reset_meas(&chan_desc->random_channel); reset_meas(&chan_desc->random_channel);
reset_meas(&chan_desc->interp_time); reset_meas(&chan_desc->interp_time);
reset_meas(&chan_desc->interp_freq); reset_meas(&chan_desc->interp_freq);
reset_meas(&chan_desc->convolution); reset_meas(&chan_desc->convolution);
} }
double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58};
...@@ -162,7 +182,7 @@ double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9}; ...@@ -162,7 +182,7 @@ double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9};
double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0}; double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0};
double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; 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_amps_lin[] = {0.3868472, 0.3094778, 0.1547389, 0.0773694, 0.0386847, 0.0193424, 0.0096712, 0.0038685};
double default_amp_lin[] = {1}; double default_amp_lin[] = {1};
double ts_shift_delays[] = {0, 1/7.68}; double ts_shift_delays[] = {0, 1/7.68};
...@@ -172,7 +192,8 @@ double ts_shift_amps[] = {0, 1}; ...@@ -172,7 +192,8 @@ double ts_shift_amps[] = {0, 1};
struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, 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.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.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}
};
struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap};
//correlation matrix for a fully correlated 2x1 channel (h1==h2) //correlation matrix for a fully correlated 2x1 channel (h1==h2)
...@@ -183,7 +204,8 @@ struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; ...@@ -183,7 +204,8 @@ struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap};
struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, 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.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.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}
};
struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap};
//correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2)
...@@ -197,7 +219,8 @@ struct complex **R_sqrt_ptr2; ...@@ -197,7 +219,8 @@ struct complex **R_sqrt_ptr2;
struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, 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.0, 0.0}, {0.0,0.0}, {0.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}}; {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}; struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap};
// full correlation matrix for TM4 to make orthogonal effective channel // full correlation matrix for TM4 to make orthogonal effective channel
...@@ -208,7 +231,8 @@ struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; ...@@ -208,7 +231,8 @@ struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap};
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}, 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.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.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.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_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap};
...@@ -217,26 +241,31 @@ struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff ...@@ -217,26 +241,31 @@ struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff
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}, 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.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.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}}; {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}; 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 //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}, 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}, {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}, {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}, {1.0,0.0}
};
struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; 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}, 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.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.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}}; {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_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}, 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.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.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}}; {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}; struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap};
...@@ -250,15 +279,12 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -250,15 +279,12 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
double channel_bandwidth, double channel_bandwidth,
double forgetting_factor, double forgetting_factor,
int32_t channel_offset, int32_t channel_offset,
double path_loss_dB) double path_loss_dB) {
{
channel_desc_t *chan_desc = (channel_desc_t *)malloc(sizeof(channel_desc_t)); channel_desc_t *chan_desc = (channel_desc_t *)malloc(sizeof(channel_desc_t));
uint16_t i,j; uint16_t i,j;
double sum_amps; double sum_amps;
double aoa,ricean_factor,Td,maxDoppler; double aoa,ricean_factor,Td,maxDoppler;
int channel_length,nb_taps; int channel_length,nb_taps;
chan_desc->nb_tx = nb_tx; chan_desc->nb_tx = nb_tx;
chan_desc->nb_rx = nb_rx; chan_desc->nb_rx = nb_rx;
chan_desc->sampling_rate = sampling_rate; chan_desc->sampling_rate = sampling_rate;
...@@ -268,7 +294,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -268,7 +294,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->path_loss_dB = path_loss_dB; chan_desc->path_loss_dB = path_loss_dB;
chan_desc->first_run = 1; chan_desc->first_run = 1;
chan_desc->ip = 0.0; chan_desc->ip = 0.0;
LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model); LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model);
switch (channel_model) { switch (channel_model) {
...@@ -276,186 +301,224 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -276,186 +301,224 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
LOG_W(OCM,"channel model not yet supported\n"); LOG_W(OCM,"channel model not yet supported\n");
free(chan_desc); free(chan_desc);
return(NULL); return(NULL);
case SCM_B: case SCM_B:
LOG_W(OCM,"channel model not yet supported\n"); LOG_W(OCM,"channel model not yet supported\n");
free(chan_desc); free(chan_desc);
return(NULL); return(NULL);
case SCM_C: case SCM_C:
chan_desc->nb_taps = 18; chan_desc->nb_taps = 18;
chan_desc->Td = 4.625; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = scm_c_delays; chan_desc->delays = scm_c_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; 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++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; 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++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
} } else {
else {
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.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); LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx);
} }
} }
break; break;
case SCM_D: 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"); 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; chan_desc->nb_taps = 18;
chan_desc->Td = 4.625; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = scm_c_delays; chan_desc->delays = scm_c_delays;
chan_desc->ricean_factor = 0.1; chan_desc->ricean_factor = 0.1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; 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++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R21_sqrt[i][0]; 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++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R12_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
} } else {
else {
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.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); LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx);
} }
} }
break; break;
case EPA: case EPA:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else {
else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.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"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
} }
break; break;
case EPA_low: case EPA_low:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0];
} } else {
else {
printf("Correlation matrices are implemented for 2 x 2 only"); printf("Correlation matrices are implemented for 2 x 2 only");
} }
/*else { /*else {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { for (i = 0; i<6; i++) {
...@@ -468,39 +531,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -468,39 +531,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
} }
}*/ }*/
break; break;
case EPA_high: case EPA_high:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0];
} } else {
else {
printf("Correlation matrices are implemented for 2 x 2 only"); printf("Correlation matrices are implemented for 2 x 2 only");
} }
/*else { /*else {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { for (i = 0; i<6; i++) {
...@@ -513,38 +585,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -513,38 +585,48 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
} }
}*/ }*/
break; break;
case EPA_medium: case EPA_medium:
chan_desc->nb_taps = 7; chan_desc->nb_taps = 7;
chan_desc->Td = .410; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = epa_delays; chan_desc->delays = epa_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(chan_desc->nb_taps*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **));
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0];
} else { } else {
printf("Correlation matrices are implemented for 2 x 2 only"); printf("Correlation matrices are implemented for 2 x 2 only");
} }
/*else { /*else {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { for (i = 0; i<6; i++) {
...@@ -557,135 +639,169 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -557,135 +639,169 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
} }
}*/ }*/
break; break;
case EVA: case EVA:
chan_desc->nb_taps = 9; chan_desc->nb_taps = 9;
chan_desc->Td = 2.51; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = eva_delays; chan_desc->delays = eva_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else {
else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.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"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
} }
break; break;
case ETU: case ETU:
chan_desc->nb_taps = 9; chan_desc->nb_taps = 9;
chan_desc->Td = 5.0; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = etu_delays; chan_desc->delays = etu_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
if (nb_tx==2 && nb_rx==2) { if (nb_tx==2 && nb_rx==2) {
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
for (i = 0; i<6; i++) for (i = 0; i<6; i++)
chan_desc->R_sqrt[i] = (struct complex*) &R22_sqrt[i][0]; chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
} } else {
else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.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"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
} }
break; break;
case MBSFN: case MBSFN:
chan_desc->nb_taps = 18; chan_desc->nb_taps = 18;
chan_desc->Td = 28.58; 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)); 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; sum_amps = 0;
chan_desc->amps = (double*) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
for (i = 0; i<chan_desc->nb_taps; i++) { for (i = 0; i<chan_desc->nb_taps; i++) {
chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]);
sum_amps += chan_desc->amps[i]; sum_amps += chan_desc->amps[i];
} }
for (i = 0; i<chan_desc->nb_taps; i++) for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->amps[i] /= sum_amps; chan_desc->amps[i] /= sum_amps;
chan_desc->delays = mbsfn_delays; chan_desc->delays = mbsfn_delays;
chan_desc->ricean_factor = 1; chan_desc->ricean_factor = 1;
chan_desc->aoa = 0; chan_desc->aoa = 0;
chan_desc->random_aoa = 0; chan_desc->random_aoa = 0;
chan_desc->ch = (struct complex**) malloc(nb_tx*nb_rx*sizeof(struct complex*)); 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->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *));
chan_desc->a = (struct complex**) malloc(chan_desc->nb_taps*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++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->ch[i] = (struct complex*) malloc(chan_desc->channel_length * sizeof(struct complex)); chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex));
for (i = 0; i<nb_tx*nb_rx; i++) for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complex*) malloc(1200 * sizeof(struct complex)); chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex));
for (i = 0; i<chan_desc->nb_taps; i++) 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->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *));
chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex*));
for (i = 0; i<6; i++) { 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)); 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)) { 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].x = 1.0;
chan_desc->R_sqrt[i][j].y = 0.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"); LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
} }
break; break;
case Rayleigh8:
case Rayleigh8:
nb_taps = 8; nb_taps = 8;
Td = 0.8; Td = 0.8;
channel_length = (int)11+2*sampling_rate*Td; channel_length = (int)11+2*sampling_rate*Td;
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc, fill_channel_desc(chan_desc,
nb_tx, nb_tx,
nb_rx, nb_rx,
...@@ -713,7 +829,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -713,7 +829,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.1; ricean_factor = 0.1;
aoa = 0.7854; aoa = 0.7854;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -740,7 +855,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -740,7 +855,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -767,7 +881,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -767,7 +881,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 800; maxDoppler = 800;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -797,11 +910,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -797,11 +910,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { if ((nb_tx==2) && (nb_rx==1)) {
R_sqrt_ptr2 = R_sqrt_21_corr; R_sqrt_ptr2 = R_sqrt_21_corr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_corr; R_sqrt_ptr2 = R_sqrt_22_corr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -833,11 +944,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -833,11 +944,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { //check this if ((nb_tx==2) && (nb_rx==1)) { //check this
R_sqrt_ptr2 = R_sqrt_21_anticorr; R_sqrt_ptr2 = R_sqrt_21_anticorr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_anticorr; R_sqrt_ptr2 = R_sqrt_22_anticorr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -866,7 +975,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -866,7 +975,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.1; ricean_factor = 0.1;
aoa = 0.7854; aoa = 0.7854;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -893,7 +1001,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -893,7 +1001,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.0; ricean_factor = 0.0;
aoa = 0.0; aoa = 0.0;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -912,7 +1019,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -912,7 +1019,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
path_loss_dB, path_loss_dB,
0); 0);
printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor); printf("AWGN: ricean_factor %f\n",chan_desc->ricean_factor);
break; break;
case TS_SHIFT: case TS_SHIFT:
...@@ -922,7 +1028,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -922,7 +1028,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
ricean_factor = 0.0; ricean_factor = 0.0;
aoa = 0.0; aoa = 0.0;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
nb_rx, nb_rx,
nb_taps, nb_taps,
...@@ -941,7 +1046,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -941,7 +1046,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
path_loss_dB, path_loss_dB,
0); 0);
printf("TS_SHIFT: ricean_factor %f\n",chan_desc->ricean_factor); printf("TS_SHIFT: ricean_factor %f\n",chan_desc->ricean_factor);
break; break;
case Rice1_corr: case Rice1_corr:
...@@ -954,11 +1058,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -954,11 +1058,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { if ((nb_tx==2) && (nb_rx==1)) {
R_sqrt_ptr2 = R_sqrt_21_corr; R_sqrt_ptr2 = R_sqrt_21_corr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_corr; R_sqrt_ptr2 = R_sqrt_22_corr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -990,11 +1092,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -990,11 +1092,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==1)) { if ((nb_tx==2) && (nb_rx==1)) {
R_sqrt_ptr2 = R_sqrt_21_anticorr; R_sqrt_ptr2 = R_sqrt_21_anticorr;
} } else if ((nb_tx==2) && (nb_rx==2)) {
else if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_anticorr; R_sqrt_ptr2 = R_sqrt_22_anticorr;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1024,11 +1124,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1024,11 +1124,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
aoa = 0.03; aoa = 0.03;
maxDoppler = 0; maxDoppler = 0;
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orthogonal; R_sqrt_ptr2 = R_sqrt_22_orthogonal;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1058,11 +1156,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1058,11 +1156,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
aoa = 0.03; aoa = 0.03;
maxDoppler = 0; maxDoppler = 0;
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1092,11 +1188,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1092,11 +1188,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
aoa = 0.03; aoa = 0.03;
maxDoppler = 0; maxDoppler = 0;
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc,nb_tx, fill_channel_desc(chan_desc,nb_tx,
...@@ -1119,22 +1213,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1119,22 +1213,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
break; break;
case Rayleigh8_orth_eff_ch_TM4_prec_real: case Rayleigh8_orth_eff_ch_TM4_prec_real:
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_real;
//R_sqrt_ptr2 = NULL; //R_sqrt_ptr2 = NULL;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
nb_taps = 8; nb_taps = 8;
Td = 0.8; Td = 0.8;
channel_length = (int)11+2*sampling_rate*Td; channel_length = (int)11+2*sampling_rate*Td;
ricean_factor = 1; ricean_factor = 1;
aoa = .03; aoa = .03;
maxDoppler = 0; maxDoppler = 0;
fill_channel_desc(chan_desc, fill_channel_desc(chan_desc,
nb_tx, nb_tx,
nb_rx, nb_rx,
...@@ -1153,7 +1243,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1153,7 +1243,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
channel_offset, channel_offset,
path_loss_dB, path_loss_dB,
0); 0);
break; break;
case Rayleigh8_orth_eff_ch_TM4_prec_imag: case Rayleigh8_orth_eff_ch_TM4_prec_imag:
...@@ -1166,8 +1255,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1166,8 +1255,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
if ((nb_tx==2) && (nb_rx==2)) { if ((nb_tx==2) && (nb_rx==2)) {
R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag; R_sqrt_ptr2 = R_sqrt_22_orth_eff_ch_TM4_prec_imag;
} } else
else
R_sqrt_ptr2 = NULL; R_sqrt_ptr2 = NULL;
fill_channel_desc(chan_desc, fill_channel_desc(chan_desc,
...@@ -1195,35 +1283,33 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, ...@@ -1195,35 +1283,33 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
free(chan_desc); free(chan_desc);
return(NULL); return(NULL);
} }
LOG_D(OCM,"[CHANNEL] RF %f\n",chan_desc->ricean_factor); 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]); 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; chan_desc->nb_paths = 10;
return(chan_desc); return(chan_desc);
} }
void free_channel_desc_scm(channel_desc_t * ch) { void free_channel_desc_scm(channel_desc_t *ch) {
// Must be made cleanly, a lot of leaks... // Must be made cleanly, a lot of leaks...
free(ch); free(ch);
} }
int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
double s; double s;
int i,k,l,aarx,aatx; int i,k,l,aarx,aatx;
struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX]; struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX];
struct complex phase, alpha, beta; struct complex phase, alpha, beta;
AssertFatal(desc->nb_tx<=NB_ANTENNAS_TX && desc->nb_rx <= NB_ANTENNAS_RX, AssertFatal(desc->nb_tx<=NB_ANTENNAS_TX && desc->nb_rx <= NB_ANTENNAS_RX,
"random_channel.c: Error: temporary buffer for channel not big enough (%d,%d)\n",desc->nb_tx,desc->nb_rx); "random_channel.c: Error: temporary buffer for channel not big enough (%d,%d)\n",desc->nb_tx,desc->nb_rx);
start_meas(&desc->random_channel); 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)].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); anew[aarx+(aatx*desc->nb_rx)].y = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0);
...@@ -1237,10 +1323,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1237,10 +1323,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
// that we can safely assume plane wave propagation. // that we can safely assume plane wave propagation.
phase.x = cos(M_PI*((aarx-aatx)*sin(desc->aoa))); phase.x = cos(M_PI*((aarx-aatx)*sin(desc->aoa)));
phase.y = sin(M_PI*((aarx-aatx)*sin(desc->aoa))); phase.y = sin(M_PI*((aarx-aatx)*sin(desc->aoa)));
anew[aarx+(aatx*desc->nb_rx)].x += phase.x * sqrt(1.0-desc->ricean_factor); 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); anew[aarx+(aatx*desc->nb_rx)].y += phase.y * sqrt(1.0-desc->ricean_factor);
} }
#ifdef DEBUG_CH #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); 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 #endif
...@@ -1263,10 +1349,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1263,10 +1349,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
alpha.y = 0.0; alpha.y = 0.0;
beta.x = 0.0; beta.x = 0.0;
beta.y = 0.0; beta.y = 0.0;
cblas_zgemv(CblasRowMajor, CblasNoTrans, desc->nb_tx*desc->nb_rx, desc->nb_tx*desc->nb_rx, cblas_zgemv(CblasRowMajor, CblasNoTrans, desc->nb_tx*desc->nb_rx, desc->nb_tx*desc->nb_rx,
(void*) &alpha, (void*) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx, (void *) &alpha, (void *) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx,
(void*) anew, 1, (void*) &beta, (void*) acorr, 1); (void *) anew, 1, (void *) &beta, (void *) acorr, 1);
/* /*
for (aarx=0;aarx<desc->nb_rx;aarx++) { for (aarx=0;aarx<desc->nb_rx;aarx++) {
...@@ -1278,10 +1363,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1278,10 +1363,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
} }
*/ */
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); cblas_zcopy(desc->nb_tx*desc->nb_rx, (void *) acorr, 1, (void *) desc->a[i], 1);
} } else {
else {
// a = alpha*acorr+beta*a // a = alpha*acorr+beta*a
// a = beta*a // a = beta*a
// a = a+alpha*acorr // a = a+alpha*acorr
...@@ -1289,9 +1373,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1289,9 +1373,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
alpha.y = 0; alpha.y = 0;
beta.x = sqrt(desc->forgetting_factor); beta.x = sqrt(desc->forgetting_factor);
beta.y = 0; beta.y = 0;
cblas_zscal(desc->nb_tx*desc->nb_rx, (void*) &beta, (void*) desc->a[i], 1); cblas_zscal(desc->nb_tx*desc->nb_rx, (void *) &beta, (void *) desc->a[i], 1);
cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void*) &alpha, (void*) acorr, 1, (void*) desc->a[i], 1); cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) acorr, 1, (void *) desc->a[i], 1);
// desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x; // desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x;
// desc->a[i][aarx+(aatx*desc->nb_rx)].y = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].y) + sqrt(1-desc->forgetting_factor)*anew.y; // desc->a[i][aarx+(aatx*desc->nb_rx)].y = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].y) + sqrt(1-desc->forgetting_factor)*anew.y;
} }
...@@ -1305,8 +1388,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1305,8 +1388,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
} }
} }
*/ */
} //nb_taps } //nb_taps
stop_meas(&desc->random_channel); stop_meas(&desc->random_channel);
//memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex)); //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex));
...@@ -1320,7 +1403,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1320,7 +1403,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
desc->ch[aarx+(aatx*desc->nb_rx)][0].x = desc->a[0][aarx+(aatx*desc->nb_rx)].x; desc->ch[aarx+(aatx*desc->nb_rx)][0].x = desc->a[0][aarx+(aatx*desc->nb_rx)].x;
desc->ch[aarx+(aatx*desc->nb_rx)][0].y = desc->a[0][aarx+(aatx*desc->nb_rx)].y; desc->ch[aarx+(aatx*desc->nb_rx)][0].y = desc->a[0][aarx+(aatx*desc->nb_rx)].y;
} else { } else {
for (k=0; k<(int)desc->channel_length; k++) { for (k=0; k<(int)desc->channel_length; k++) {
desc->ch[aarx+(aatx*desc->nb_rx)][k].x = 0.0; desc->ch[aarx+(aatx*desc->nb_rx)][k].x = 0.0;
desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0; desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0;
...@@ -1335,7 +1417,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1335,7 +1417,6 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x; desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x;
desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y; desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y;
// printf("l %d : desc->ch.x %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x); // printf("l %d : desc->ch.x %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x);
} //nb_taps } //nb_taps
#ifdef DEBUG_CH #ifdef DEBUG_CH
...@@ -1346,6 +1427,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1346,6 +1427,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
} //channel_length } //channel_length
} //aatx } //aatx
} //aarx } //aarx
stop_meas(&desc->interp_time); stop_meas(&desc->interp_time);
} }
...@@ -1355,9 +1437,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { ...@@ -1355,9 +1437,9 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
return (0); return (0);
} }
double N_RB2sampling_rate(uint16_t N_RB) double N_RB2sampling_rate(uint16_t N_RB) {
{
double sampling_rate; double sampling_rate;
switch (N_RB) { switch (N_RB) {
case 6: case 6:
sampling_rate = 1.92; sampling_rate = 1.92;
...@@ -1382,9 +1464,9 @@ double N_RB2sampling_rate(uint16_t N_RB) ...@@ -1382,9 +1464,9 @@ double N_RB2sampling_rate(uint16_t N_RB)
return(sampling_rate); return(sampling_rate);
} }
double N_RB2channel_bandwidth(uint16_t N_RB) double N_RB2channel_bandwidth(uint16_t N_RB) {
{
double channel_bandwidth; double channel_bandwidth;
switch (N_RB) { switch (N_RB) {
case 6: case 6:
channel_bandwidth = 1.25; channel_bandwidth = 1.25;
...@@ -1406,18 +1488,52 @@ double N_RB2channel_bandwidth(uint16_t N_RB) ...@@ -1406,18 +1488,52 @@ double N_RB2channel_bandwidth(uint16_t N_RB)
LOG_E(PHY,"Unknown N_PRB\n"); LOG_E(PHY,"Unknown N_PRB\n");
return(-1); return(-1);
} }
return(channel_bandwidth); return(channel_bandwidth);
} }
static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
for(int i=0; channelmod_names[i].name != NULL ; i++) {
prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i ));
}
return 0;
}
int modelid_fromname(char *modelname) {
int modelid=map_str_to_int(channelmod_names,modelname);
AssertFatal(modelid>0,
"random_channel.c: Error channel model %s unknown\n",modelname);
return modelid;
}
double channelmod_get_snr_dB(void) {
return snr_dB;
}
double channelmod_get_sinr_dB(void) {
return sinr_dB;
}
void init_channelmod(void) {
paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC;
int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed");
/* look for telnet server, if it is loaded, add the channel modeling commands to it */
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
if (addcmd != NULL) {
addcmd("channelmod",channelmod_vardef,channelmod_cmdarray);
}
}
#ifdef RANDOM_CHANNEL_MAIN #ifdef RANDOM_CHANNEL_MAIN
#define sampling_rate 5.0 #define sampling_rate 5.0
#define Td 2.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}; double amps[8] = {.8,.2,.1,.04,.02,.01,.005};
struct complex ch[(int)(1+2*sampling_rate*Td)],phase; struct complex ch[(int)(1+2*sampling_rate*Td)],phase;
int i; int i;
randominit(); randominit();
phase.x = 1.0; phase.x = 1.0;
phase.y = 0; phase.y = 0;
......
...@@ -147,7 +147,7 @@ typedef struct { ...@@ -147,7 +147,7 @@ typedef struct {
/// Rice factor??? /// Rice factor???
/// Walls (penetration loss) /// Walls (penetration loss)
/// Nodes in the scenario /// Nodes in the scenario
node_desc_t* nodes; node_desc_t *nodes;
} scenario_desc_t; } scenario_desc_t;
typedef enum { typedef enum {
...@@ -180,6 +180,43 @@ typedef enum { ...@@ -180,6 +180,43 @@ typedef enum {
EPA_medium, EPA_medium,
EPA_high, EPA_high,
} SCM_t; } SCM_t;
#define CHANNELMOD_MAP_INIT \
{"custom",custom},\
{"SCM_A",SCM_A},\
{"SCM_B",SCM_B},\
{"SCM_C",SCM_C},\
{"SCM_D",SCM_D},\
{"EPA",EPA},\
{"EVA",EVA},\
{"ETU",ETU},\
{"MBSFN",MBSFN},\
{"Rayleigh8",Rayleigh8},\
{"Rayleigh1",Rayleigh1},\
{"Rayleigh1_800",Rayleigh1_800},\
{"Rayleigh1_corr",Rayleigh1_corr},\
{"Rayleigh1_anticorr",Rayleigh1_anticorr},\
{"Rice8",Rice8},\
{"Rice1",Rice1},\
{"Rice1_corr",Rice1_corr},\
{"Rice1_anticorr",Rice1_anticorr},\
{"AWGN",AWGN},\
{"Rayleigh1_orthogonal",Rayleigh1_orthogonal},\
{"Rayleigh1_orth_eff_ch_TM4_prec_real",Rayleigh1_orth_eff_ch_TM4_prec_real},\
{"Rayleigh1_orth_eff_ch_TM4_prec_imag",Rayleigh1_orth_eff_ch_TM4_prec_imag},\
{"Rayleigh8_orth_eff_ch_TM4_prec_real",Rayleigh8_orth_eff_ch_TM4_prec_real},\
{"Rayleigh8_orth_eff_ch_TM4_prec_imag",Rayleigh8_orth_eff_ch_TM4_prec_imag},\
{"TS_SHIFT",TS_SHIFT},\
{"EPA_low",EPA_low},\
{"EPA_medium",EPA_medium},\
{"EPA_high",EPA_high},\
{NULL, -1}
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
#define CHANNELMOD_SECTION "channelmod"
#define CHANNELMOD_PARAMS_DESC { \
{"s" ,CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED , dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\
{"sinr_dB" ,NULL, 0 , dblptr:&sinr_dB, defdblval:0, TYPE_DOUBLE, 0},\
}
#include "platform_constants.h" #include "platform_constants.h"
...@@ -395,9 +432,23 @@ void multipath_tv_channel(channel_desc_t *desc, ...@@ -395,9 +432,23 @@ void multipath_tv_channel(channel_desc_t *desc,
/**@} */ /**@} */
/**@} */ /**@} */
void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig,
int rxAnt,
channel_desc_t *channelDesc,
int nbSamples,
uint64_t TS,
uint32_t CirSize
);
int modelid_fromname(char *modelname);
double channelmod_get_snr_dB(void);
double channelmod_get_sinr_dB(void);
void init_channelmod(void) ;
double N_RB2sampling_rate(uint16_t N_RB); double N_RB2sampling_rate(uint16_t N_RB);
double N_RB2channel_bandwidth(uint16_t N_RB); double N_RB2channel_bandwidth(uint16_t N_RB);
#include "targets/RT/USER/rfsim.h" #include "targets/RT/USER/rfsim.h"
void do_DL_sig(sim_t *sim, void do_DL_sig(sim_t *sim,
...@@ -412,6 +463,7 @@ void do_UL_sig(sim_t *sim, ...@@ -412,6 +463,7 @@ void do_UL_sig(sim_t *sim,
uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms,
uint32_t frame,int ru_id,uint8_t CC_id); uint32_t frame,int ru_id,uint8_t CC_id);
#endif #endif
...@@ -410,7 +410,6 @@ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_ ...@@ -410,7 +410,6 @@ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_
#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) #define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
#define sample_t struct complex16 // 2*16 bits complex number
typedef struct { typedef struct {
uint64_t magic; // Magic value (see defines above) uint64_t magic; // Magic value (see defines above)
......
#General # General
This is a RF simulator that allows to test OAI without a RF board. This is a RF simulator that allows to test OAI without a RF board.
It replaces a actual RF board driver. It replaces a actual RF board driver.
As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound) As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound)
#build # build
## From build_oai ## From [build_oai](../../../doc/BUILD.md) script
You can build it the same way, and together with actual RF driver The RF simulator is implemented as an oai device and is always build when you build the oai eNB or the oai UE.
Using the `-w SIMU` option it is possible to just re-build the RF simulator device
Example: Example:
```bash ```bash
./build_oai --ue-nas-use-tun --UE --eNB -w SIMU ./build_oai --UE --eNB
Will compile UE
Will compile eNB
CMAKE_CMD=cmake ..
No local radio head and no transport protocol selected
No radio head has been selected (HW set to None)
No transport protocol has been selected (TP set to None)
RF HW set to None
Flags for Deadline scheduler: False
..................
.................
Compiling rfsimulator
Log file for compilation has been written to: /usr/local/oai/rfsimu_config/openairinterface5g/cmake_targets/log/rfsimulator.Rel14.txt
rfsimulator compiled
......................
......................
``` ```
It is also possible to build actual RF and use choose on each run:
```bash
./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator
```
Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem)
We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver.
## Add the rfsimulator after initial build ## Add the rfsimulator after initial build
After any regular build, you can compile the driver After any regular build, you can compile the device, from the build directory
```bash ```bash
cd <the_compilation_dir_from_bouild_oai_script>/build cd <path to oai sources>/openairinterface5g/cmake_targets/lte_build_oai/build
make rfsimulator make rfsimulator
``` ```
Then, you can use it freely this is equivalent to using `-w SIMU` when running the `build_oai` script.
e
# Usage # Usage
Setting the env variable RFSIMULATOR enables the RF board simulator To use the RF simulator you add the `--rfsim` option to the command line. By default the RF simulator device will try to connect to host 127.0.0.1, port 4043, which is usually the behavior for the UE.
It should the set to "server" in the eNB or gNB The RF simulator is using the configuration module, its parameters are defined in a specific section called "rfsimulator"
| parameter | usage | default |
|:---------------------|:------------------------------------------------------------------------------------------------------------------|----:|
| serveraddr | ip address to connect to, or "enb" to behave as a tcp server | 127.0.0.1 |
| serverport | port number to connect to or to listen on (eNB, which behaved as a tcp server) | 4043 |
| options | list of comma separated run-time options, two are supported: `chanmod` to enable channel modeling and `saviq` to write transmitted iqs to a file | all options disabled |
| modelname | Name of the channel model to apply on received iqs when the `chanmod` option is enabled | AWGN |
| IQfile | Path to the file to be used to store iqs, when the `saviq`option is enabled | /tmp/rfsimulator.iqs |
Setting the env variable RFSIMULATOR can be used instead of using the serveraddr parameter, it is to preserve compatibility with previous version.
## 4G case ## 4G case
For the UE, it should be set to the IP address of the eNB For the UE, it should be set to the IP address of the eNB
...@@ -38,13 +59,14 @@ example: ...@@ -38,13 +59,14 @@ example:
```bash ```bash
sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50
``` ```
Except this, the UE and the eNB can be used as it the RF is real Except this, the UE and the eNB can be used as it the RF is real. noS1 mode can also be used with the RF simulator.
If you reach 'RA not active' on UE, be careful to generate a valid SIM If you reach 'RA not active' on UE, be careful to generate a valid SIM.
```bash ```bash
$OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o . $OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o .
``` ```
## 5G case ## 5G case
5G RF simulator will be aligned with 4G as the effort to merge 5G specifuc branches into develop is making progress.
After regular build, add the simulation driver After regular build, add the simulation driver
(don't use ./build_oai -w SIMU until we merge 4G and 5G branches) (don't use ./build_oai -w SIMU until we merge 4G and 5G branches)
```bash ```bash
...@@ -66,7 +88,7 @@ In UE, you can add "-d" to get the softscope ...@@ -66,7 +88,7 @@ In UE, you can add "-d" to get the softscope
You can store emitted I/Q samples: You can store emitted I/Q samples:
If you set the environment variable: saveIQfile to a file name If you set the option `saviq`
The simulator will write all IQ samples into this file The simulator will write all IQ samples into this file
Then, you can replay with the executable "replay_node" Then, you can replay with the executable "replay_node"
...@@ -83,11 +105,11 @@ If you have existing stored I/Q, you can adpat the tool "replay_node" to convert ...@@ -83,11 +105,11 @@ If you have existing stored I/Q, you can adpat the tool "replay_node" to convert
The format intend to be compatible with the OAI store/replay feature on USRP The format intend to be compatible with the OAI store/replay feature on USRP
### Channel simulation ### Channel simulation
The RF channel simulator is called. When the `chanmod` option is enabled, The RF channel simulator is called.
In current version all channel paramters are hard coded in the call to: In current version all channel paramters are set depending on the model name via a call to:
``` ```
new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
AWGN, <model name>,
bridge->sample_rate, bridge->sample_rate,
bridge->tx_bw, bridge->tx_bw,
0.0, // forgetting_factor 0.0, // forgetting_factor
...@@ -95,7 +117,7 @@ new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, ...@@ -95,7 +117,7 @@ new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
0); // path_loss in dB 0); // path_loss in dB
``` ```
Only the input noise can be changed on command line with -s parameter. Only the input noise can be changed on command line with -s parameter.
With path loss = 0 set "-s 5" to see a little noise With path loss = 0 set "-s 5" to see a little noise. -s is a shortcut to `channelmod.s`. It is expected to enhance the channel modedelization flexibility via the addition of more parameters in the channelmod section.
#Caveacts # Caveacts
Still issues in power control: txgain, rxgain are not used Still issues in power control: txgain, rxgain are not used
/*
Author: Laurent THOMAS, Open Cells for Nokia
copyleft: OpenAirInterface Software Alliance and it's licence
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include <common/config/config_userapi.h>
#include <openair1/SIMULATION/TOOLS/sim.h>
/*
Legacy study:
The parameters are:
gain&loss (decay, signal power, ...)
either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
=> don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
multi_path (auto convolution, ISI, ...)
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
legacy: we regenerate each sub frame in UL, and each frame only in DL
*/
void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig,
int rxAnt,
channel_desc_t *channelDesc,
int nbSamples,
uint64_t TS,
uint32_t CirSize
) {
// channelDesc->path_loss_dB should contain the total path gain
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
// UE and NB gain control to be added
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
// Energy in one sample to calibrate input noise
//Fixme: modified the N0W computation, not understand the origin value
const double KT=1.38e-23*290; //Boltzman*temperature
// sampling rate is linked to acquisition band (the input pass band filter)
const double noise_figure_watt = KT*channelDesc->sampling_rate;
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
// the parameter "-s" is declared as SNR, but the input power is not well defined
// −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
const double rxGain= 132.24 - channelmod_get_snr_dB();
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
// fixme: the last constant is pure trial results to make decent noise
const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
// Fixme: we don't fill the offset length samples at begining ?
// anyway, in today code, channel_offset=0
const int dd = abs(channelDesc->channel_offset);
const int nbTx=channelDesc->nb_tx;
for (int i=0; i<((int)nbSamples-dd); i++) {
struct complex16 *out_ptr=after_channel_sig+dd+i;
struct complex rx_tmp= {0};
for (int txAnt=0; txAnt < nbTx; txAnt++) {
const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)];
//const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
for (int l = 0; l<(int)channelDesc->channel_length; l++) {
// let's assume TS+i >= l
// fixme: the rfsimulator current structure is interleaved antennas
// this has been designed to not have to wait a full block transmission
// but it is not very usefull
// it would be better to split out each antenna in a separate flow
// that will allow to mix ru antennas freely
struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize];
rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y;
rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y;
} //l
}
out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
out_ptr++;
}
if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
// Cast to a wrong type for compatibility !
LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
channelDesc->path_loss_dB,
10*log10(noise_per_sample));
}
...@@ -24,12 +24,15 @@ ...@@ -24,12 +24,15 @@
#include <common/utils/assertions.h> #include <common/utils/assertions.h>
#include <common/utils/LOG/log.h> #include <common/utils/LOG/log.h>
#include <common/utils/load_module_shlib.h>
#include <common/config/config_userapi.h>
#include "common_lib.h" #include "common_lib.h"
#include <openair1/PHY/defs_eNB.h> #include <openair1/PHY/defs_eNB.h>
#include "openair1/PHY/defs_UE.h" #include "openair1/PHY/defs_UE.h"
#define CHANNELMOD_DYNAMICLOAD
#include <openair1/SIMULATION/TOOLS/sim.h> #include <openair1/SIMULATION/TOOLS/sim.h>
#define PORT 4043 //TCP port for this simulator #define PORT 4043 //default TCP port for this simulator
#define CirSize 3072000 // 100ms is enough #define CirSize 3072000 // 100ms is enough
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
...@@ -39,12 +42,31 @@ ...@@ -39,12 +42,31 @@
// Fixme: datamodel, external variables in .h files, ... // Fixme: datamodel, external variables in .h files, ...
#include <common/ran_context.h> #include <common/ran_context.h>
extern double snr_dB;
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
// //
#define RFSIMU_SECTION "rfsimulator"
#define RFSIMU_OPTIONS_PARAMNAME "options"
# define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\
" chanmod: enable channel modelisation\n"\
" saviq: enable saving written iqs to a file\n"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* configuration parameters for the rfsimulator device */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define RFSIMULATOR_PARAMS_DESC {\
{"serveraddr", "<ip address to connect to>\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\
{"serverport", "<port to connect to>\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\
{RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0},\
{"IQfile", "<file path to use when saving IQs>\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\
{"modelname", "<channel model name>\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 }\
};
pthread_mutex_t Sockmutex; pthread_mutex_t Sockmutex;
typedef struct complex16 sample_t; // 2*16 bits complex number
typedef struct buffer_s { typedef struct buffer_s {
int conn_sock; int conn_sock;
openair0_timestamp lastReceivedTS; openair0_timestamp lastReceivedTS;
...@@ -63,90 +85,16 @@ typedef struct { ...@@ -63,90 +85,16 @@ typedef struct {
openair0_timestamp nextTimestamp; openair0_timestamp nextTimestamp;
uint64_t typeStamp; uint64_t typeStamp;
char *ip; char *ip;
uint16_t port;
int saveIQfile; int saveIQfile;
buffer_t buf[FD_SETSIZE]; buffer_t buf[FD_SETSIZE];
int rx_num_channels; int rx_num_channels;
int tx_num_channels; int tx_num_channels;
double sample_rate; double sample_rate;
double tx_bw; double tx_bw;
int channelmod;
} rfsimulator_state_t; } rfsimulator_state_t;
/*
Legacy study:
The parameters are:
gain&loss (decay, signal power, ...)
either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
=> don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
multi_path (auto convolution, ISI, ...)
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
legacy: we regenerate each sub frame in UL, and each frame only in DL
*/
void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig,
int rxAnt,
channel_desc_t *channelDesc,
int nbSamples,
uint64_t TS
) {
// channelDesc->path_loss_dB should contain the total path gain
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
// UE and NB gain control to be added
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
// Energy in one sample to calibrate input noise
//Fixme: modified the N0W computation, not understand the origin value
const double KT=1.38e-23*290; //Boltzman*temperature
// sampling rate is linked to acquisition band (the input pass band filter)
const double noise_figure_watt = KT*channelDesc->sampling_rate;
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
// the parameter "-s" is declared as SNR, but the input power is not well defined
// −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
const double rxGain= 132.24 - snr_dB;
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
// fixme: the last constant is pure trial results to make decent noise
const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
// Fixme: we don't fill the offset length samples at begining ?
// anyway, in today code, channel_offset=0
const int dd = abs(channelDesc->channel_offset);
const int nbTx=channelDesc->nb_tx;
for (int i=0; i<((int)nbSamples-dd); i++) {
struct complex16 *out_ptr=after_channel_sig+dd+i;
struct complex rx_tmp= {0};
for (int txAnt=0; txAnt < nbTx; txAnt++) {
const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)];
//const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
for (int l = 0; l<(int)channelDesc->channel_length; l++) {
// let's assume TS+i >= l
// fixme: the rfsimulator current structure is interleaved antennas
// this has been designed to not have to wait a full block transmission
// but it is not very usefull
// it would be better to split out each antenna in a separate flow
// that will allow to mix ru antennas freely
struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize];
rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y;
rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y;
} //l
}
out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
out_ptr++;
}
if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
// Cast to a wrong type for compatibility !
LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
channelDesc->path_loss_dB,
10*log10(noise_per_sample));
}
void allocCirBuf(rfsimulator_state_t *bridge, int sock) { void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
buffer_t *ptr=&bridge->buf[sock]; buffer_t *ptr=&bridge->buf[sock];
...@@ -164,6 +112,8 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -164,6 +112,8 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
ev.events = EPOLLIN | EPOLLRDHUP; ev.events = EPOLLIN | EPOLLRDHUP;
ev.data.fd = sock; ev.data.fd = sock;
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
if ( bridge->channelmod > 0) {
// create channel simulation model for this mode reception // create channel simulation model for this mode reception
// snr_dB is pure global, coming from configuration paramter "-s" // snr_dB is pure global, coming from configuration paramter "-s"
// Fixme: referenceSignalPower should come from the right place // Fixme: referenceSignalPower should come from the right place
...@@ -177,13 +127,14 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -177,13 +127,14 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
// Legacy changes directlty the variable channel_model->path_loss_dB place to place // Legacy changes directlty the variable channel_model->path_loss_dB place to place
// while calling new_channel_desc_scm() with path losses = 0 // while calling new_channel_desc_scm() with path losses = 0
ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
AWGN, bridge->channelmod,
bridge->sample_rate, bridge->sample_rate,
bridge->tx_bw, bridge->tx_bw,
0.0, // forgetting_factor 0.0, // forgetting_factor
0, // maybe used for TA 0, // maybe used for TA
0); // path_loss in dB 0); // path_loss in dB
random_channel(ptr->channel_model,false); random_channel(ptr->channel_model,false);
}
} }
void removeCirBuf(rfsimulator_state_t *bridge, int sock) { void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
...@@ -212,6 +163,7 @@ void socketError(rfsimulator_state_t *bridge, int sock) { ...@@ -212,6 +163,7 @@ void socketError(rfsimulator_state_t *bridge, int sock) {
rfsimulator: error: you have to run one UE and one eNB\n\ rfsimulator: error: you have to run one UE and one eNB\n\
For this, export RFSIMULATOR=enb (eNB case) or \n\ For this, export RFSIMULATOR=enb (eNB case) or \n\
RFSIMULATOR=<an ip address> (UE case)\n\ RFSIMULATOR=<an ip address> (UE case)\n\
or use rfsimulator.serveraddr configuration option\n\
\x1b[m" \x1b[m"
enum blocking_t { enum blocking_t {
...@@ -266,6 +218,48 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { ...@@ -266,6 +218,48 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
} }
} }
void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
char *saveF=NULL;
char *modelname=NULL;
paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
int p = config_paramidx_fromname(rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t), RFSIMU_OPTIONS_PARAMNAME) ;
int ret = config_get( rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t),RFSIMU_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed");
rfsimulator->saveIQfile = -1;
for(int i=0; i<rfsimu_params[p].numelt ; i++) {
if (strcmp(rfsimu_params[p].strlistptr[i],"saviq") == 0) {
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
if ( rfsimulator->saveIQfile != -1 )
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
else
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
break;
} else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) {
init_channelmod();
rfsimulator->channelmod=modelid_fromname(modelname);
} else {
fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]);
exit(-1);
}
}
/* for compatibility keep environment variable usage */
if ( getenv("RFSIMULATOR") != NULL ) {
rfsimulator->ip=getenv("RFSIMULATOR");
}
if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
strncasecmp(rfsimulator->ip,"server",3) == 0 )
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
else
rfsimulator->typeStamp = UE_MAGICDL_FDD;
}
int server_start(openair0_device *device) { int server_start(openair0_device *device) {
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
t->typeStamp=ENB_MAGICDL_FDD; t->typeStamp=ENB_MAGICDL_FDD;
...@@ -276,7 +270,7 @@ int server_start(openair0_device *device) { ...@@ -276,7 +270,7 @@ int server_start(openair0_device *device) {
sin_family: sin_family:
AF_INET, AF_INET,
sin_port: sin_port:
htons(PORT), htons(t->port),
sin_addr: sin_addr:
{ s_addr: INADDR_ANY } { s_addr: INADDR_ANY }
}; };
...@@ -298,7 +292,7 @@ int start_ue(openair0_device *device) { ...@@ -298,7 +292,7 @@ int start_ue(openair0_device *device) {
sin_family: sin_family:
AF_INET, AF_INET,
sin_port: sin_port:
htons(PORT), htons(t->port),
sin_addr: sin_addr:
{ s_addr: INADDR_ANY } { s_addr: INADDR_ANY }
}; };
...@@ -306,7 +300,7 @@ sin_addr: ...@@ -306,7 +300,7 @@ sin_addr:
bool connected=false; bool connected=false;
while(!connected) { while(!connected) {
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, PORT); LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, t->port);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
LOG_I(HW,"rfsimulator: connection established\n"); LOG_I(HW,"rfsimulator: connection established\n");
...@@ -326,13 +320,13 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi ...@@ -326,13 +320,13 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
rfsimulator_state_t *t = device->priv; rfsimulator_state_t *t = device->priv;
LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
for (int i=0; i<FD_SETSIZE; i++) { for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *b=&t->buf[i]; buffer_t *b=&t->buf[i];
if (b->conn_sock >= 0 ) { if (b->conn_sock >= 0 ) {
if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize) if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize)
LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS); LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
fullwrite(b->conn_sock,&header, sizeof(header), t); fullwrite(b->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[nsamps][nbAnt]; sample_t tmpSamples[nsamps][nbAnt];
...@@ -487,18 +481,23 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ...@@ -487,18 +481,23 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
if ( first_sock == FD_SETSIZE ) { if ( first_sock == FD_SETSIZE ) {
// no connected device (we are eNB, no UE is connected) // no connected device (we are eNB, no UE is connected)
if ( t->nextTimestamp == 0)
LOG_W(HW,"No connected device, generating void samples...\n");
if (!flushInput(t, 10)) { if (!flushInput(t, 10)) {
for (int x=0; x < nbAnt; x++) for (int x=0; x < nbAnt; x++)
memset(samplesVoid[x],0,sampleToByte(nsamps,1)); memset(samplesVoid[x],0,sampleToByte(nsamps,1));
t->nextTimestamp+=nsamps; t->nextTimestamp+=nsamps;
if ( ((t->nextTimestamp/nsamps)%100) == 0)
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
*ptimestamp = t->nextTimestamp-nsamps; *ptimestamp = t->nextTimestamp-nsamps;
pthread_mutex_unlock(&Sockmutex); pthread_mutex_unlock(&Sockmutex);
return nsamps; return nsamps;
} }
} else { } else {
bool have_to_wait; bool have_to_wait;
do { do {
...@@ -506,19 +505,23 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ...@@ -506,19 +505,23 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
for ( int sock=0; sock<FD_SETSIZE; sock++) { for ( int sock=0; sock<FD_SETSIZE; sock++) {
buffer_t *b=&t->buf[sock]; buffer_t *b=&t->buf[sock];
if ( b->circularBuf) { if ( b->circularBuf) {
LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n", LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n",
sock, b->lastWroteTS, sock, b->lastWroteTS,
b->lastReceivedTS, b->lastReceivedTS,
t->nextTimestamp+nsamps); t->nextTimestamp+nsamps);
if ( b->lastReceivedTS > b->lastWroteTS ) { if ( b->lastReceivedTS > b->lastWroteTS ) {
// The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance // The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
// This occurs for example when UE is in sync mode: it doesn't transmit // This occurs for example when UE is in sync mode: it doesn't transmit
// with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
struct complex16 v={0}; struct complex16 v= {0};
void *samplesVoid[b->th.nbAnt]; void *samplesVoid[b->th.nbAnt];
for ( int i=0; i <b->th.nbAnt; i++) for ( int i=0; i <b->th.nbAnt; i++)
samplesVoid[i]=(void*)&v; samplesVoid[i]=(void *)&v;
rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0); rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
} }
} }
...@@ -555,13 +558,24 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ...@@ -555,13 +558,24 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
if (reGenerateChannel) if (reGenerateChannel)
random_channel(ptr->channel_model,0); random_channel(ptr->channel_model,0);
for (int a=0; a<nbAnt; a++) for (int a=0; a<nbAnt; a++) {
if ( ptr->channel_model != NULL ) // apply a channel model
rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a], rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a],
a, a,
ptr->channel_model, ptr->channel_model,
nsamps, nsamps,
t->nextTimestamp t->nextTimestamp,
CirSize
); );
else { // no channel modeling
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ ) {
out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].r;
out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].i;
}
} // end of no channel modeling
} // end for a...
} }
} }
...@@ -603,33 +617,9 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { ...@@ -603,33 +617,9 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
// to change the log level, use this on command line // to change the log level, use this on command line
// --log_config.hw_log_level debug // --log_config.hw_log_level debug
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
rfsimulator_readconfig(rfsimulator);
if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) {
LOG_E(HW,helpTxt);
exit(1);
}
pthread_mutex_init(&Sockmutex, NULL); pthread_mutex_init(&Sockmutex, NULL);
if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
strncasecmp(rfsimulator->ip,"server",3) == 0 )
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
else
rfsimulator->typeStamp = UE_MAGICDL_FDD;
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE"); LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
char *saveF;
if ((saveF=getenv("saveIQfile")) != NULL) {
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
if ( rfsimulator->saveIQfile != -1 )
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
else
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
} else
rfsimulator->saveIQfile = -1;
device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ? device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
server_start : server_start :
start_ue; start_ue;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <common/utils/simple_executable.h> #include <common/utils/simple_executable.h>
volatile int oai_exit = 0;
void fullwrite(int fd, void *_buf, int count) { void fullwrite(int fd, void *_buf, int count) {
char *buf = _buf; char *buf = _buf;
...@@ -123,7 +124,7 @@ int main(int argc, char *argv[]) { ...@@ -123,7 +124,7 @@ int main(int argc, char *argv[]) {
setblocking(serviceSock, blocking); setblocking(serviceSock, blocking);
AssertFatal(read(fd,&header,sizeof(header)), ""); AssertFatal(read(fd,&header,sizeof(header)), "");
fullwrite(serviceSock, &header, sizeof(header)); fullwrite(serviceSock, &header, sizeof(header));
int dataSize=sizeof(sample_t)*header.size*header.nbAnt; int dataSize=sizeof(int32_t)*header.size*header.nbAnt;
if (dataSize>bufSize) { if (dataSize>bufSize) {
void * new_buff = realloc(buff, dataSize); void * new_buff = realloc(buff, dataSize);
......
...@@ -275,12 +275,24 @@ NETWORK_CONTROLLER : ...@@ -275,12 +275,24 @@ NETWORK_CONTROLLER :
THREAD_STRUCT = ( THREAD_STRUCT = (
{ {
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; parallel_config = "PARALLEL_SINGLE_THREAD";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_ENABLE"; worker_config = "WORKER_ENABLE";
} }
); );
/*
#example config for rfsimulator
rfsimulator :
{
serveraddr = "enb";
serverport = "4043";
options = ("saviq");
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
*/
log_config : log_config :
{ {
global_log_level ="info"; global_log_level ="info";
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
static softmodem_params_t softmodem_params; static softmodem_params_t softmodem_params;
char *parallel_config=NULL; char *parallel_config=NULL;
char *worker_config=NULL; char *worker_config=NULL;
double snr_dB=25;
uint64_t get_softmodem_optmask(void) { uint64_t get_softmodem_optmask(void) {
return softmodem_params.optmask; return softmodem_params.optmask;
......
...@@ -78,7 +78,6 @@ ...@@ -78,7 +78,6 @@
#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" #define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n"
#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" #define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" #define CONFIG_HLP_UE "Set the lte softmodem as a UE\n"
#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" #define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"
#define CONFIG_HLP_TPORT "tracer port\n" #define CONFIG_HLP_TPORT "tracer port\n"
...@@ -200,7 +199,6 @@ ...@@ -200,7 +199,6 @@
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
{"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \ {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
...@@ -285,8 +283,6 @@ uint64_t get_pdcp_optmask(void); ...@@ -285,8 +283,6 @@ uint64_t get_pdcp_optmask(void);
extern pthread_cond_t sync_cond; extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex; extern pthread_mutex_t sync_mutex;
extern int sync_var; extern int sync_var;
extern double snr_dB;
extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
...@@ -311,7 +307,7 @@ extern void stop_eNB(int); ...@@ -311,7 +307,7 @@ extern void stop_eNB(int);
extern void kill_eNB_proc(int inst); extern void kill_eNB_proc(int inst);
// In lte-ru.c // In lte-ru.c
extern void init_RU(char*,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync); extern void init_RU(char *,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
extern void stop_ru(RU_t *ru); extern void stop_ru(RU_t *ru);
extern void init_ru_vnf(void); extern void init_ru_vnf(void);
extern void init_RU_proc(RU_t *ru); extern void init_RU_proc(RU_t *ru);
...@@ -337,7 +333,7 @@ extern void kill_td_thread(PHY_VARS_eNB *); ...@@ -337,7 +333,7 @@ extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *); extern void kill_te_thread(PHY_VARS_eNB *);
extern void RCConfig_sim(void); extern void RCConfig_sim(void);
extern void init_ocm(double,double); extern void init_ocm(void);
extern void init_ue_devices(PHY_VARS_UE *); extern void init_ue_devices(PHY_VARS_UE *);
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
......
...@@ -323,12 +323,10 @@ static void get_options(void) { ...@@ -323,12 +323,10 @@ static void get_options(void) {
int CC_id; int CC_id;
int tddflag; int tddflag;
char *loopfile=NULL; char *loopfile=NULL;
int dumpframe=0; int dumpframe=0;
int timingadv; int timingadv;
uint8_t nfapi_mode; uint8_t nfapi_mode;
int simL1flag ; int simL1flag ;
set_default_frame_parms(frame_parms); set_default_frame_parms(frame_parms);
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
/* unknown parameters on command line will be checked in main /* unknown parameters on command line will be checked in main
...@@ -811,7 +809,7 @@ int main( int argc, char **argv ) { ...@@ -811,7 +809,7 @@ int main( int argc, char **argv ) {
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
if (IS_SOFTMODEM_SIML1 ) { if (IS_SOFTMODEM_SIML1 ) {
init_ocm(snr_dB,0); init_ocm();
PHY_vars_UE_g[0][0]->no_timing_correction = 1; PHY_vars_UE_g[0][0]->no_timing_correction = 1;
} }
......
...@@ -63,14 +63,12 @@ sim_t sim; ...@@ -63,14 +63,12 @@ sim_t sim;
void init_ru_devices(void); void init_ru_devices(void);
void init_RU(char*,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync); void init_RU(char *,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
void *rfsim_top(void *n_frames); void *rfsim_top(void *n_frames);
void wait_RUs(void) void wait_RUs(void) {
{
int i; int i;
// wait for all RUs to be configured over fronthaul // wait for all RUs to be configured over fronthaul
pthread_mutex_lock(&RC.ru_mutex); pthread_mutex_lock(&RC.ru_mutex);
...@@ -81,47 +79,36 @@ void wait_RUs(void) ...@@ -81,47 +79,36 @@ void wait_RUs(void)
pthread_mutex_unlock(&RC.ru_mutex); pthread_mutex_unlock(&RC.ru_mutex);
// copy frame parameters from RU to UEs // copy frame parameters from RU to UEs
for (i=0;i<NB_UE_INST;i++) { for (i=0; i<NB_UE_INST; i++) {
sim.current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms.samples_per_tti + RC.ru[0]->frame_parms.ofdm_symbol_size + RC.ru[0]->frame_parms.nb_prefix_samples0; sim.current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms.samples_per_tti + RC.ru[0]->frame_parms.ofdm_symbol_size + RC.ru[0]->frame_parms.nb_prefix_samples0;
} }
for (int ru_id=0;ru_id<RC.nb_RU;ru_id++) sim.current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms.samples_per_tti; for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) sim.current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms.samples_per_tti;
printf("RUs are ready, let's go\n"); printf("RUs are ready, let's go\n");
} }
void wait_eNBs(void) void wait_eNBs(void) {
{
return; return;
} }
void RCConfig_sim(void) { void RCConfig_sim(void) {
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
// Get num RU instances // Get num RU instances
config_getlist( &RUParamList,NULL,0, NULL); config_getlist( &RUParamList,NULL,0, NULL);
RC.nb_RU = RUParamList.numelt; RC.nb_RU = RUParamList.numelt;
AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n"); AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n");
printf("returned with %d rus\n",RC.nb_RU); printf("returned with %d rus\n",RC.nb_RU);
init_RU(NULL,internal,internal,0); init_RU(NULL,internal,internal,0);
printf("Waiting for RUs to get set up\n"); printf("Waiting for RUs to get set up\n");
wait_RUs(); wait_RUs();
init_ru_devices(); init_ru_devices();
static int nframes = 100000; static int nframes = 100000;
AssertFatal(0 == pthread_create(&sim.rfsim_thread, AssertFatal(0 == pthread_create(&sim.rfsim_thread,
NULL, NULL,
rfsim_top, rfsim_top,
(void*)&nframes), ""); (void *)&nframes), "");
} }
...@@ -164,16 +151,11 @@ extern int subframe_ru_mask,subframe_UE_mask; ...@@ -164,16 +151,11 @@ extern int subframe_ru_mask,subframe_UE_mask;
int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int ru_id = device->Mod_id; int ru_id = device->Mod_id;
int CC_id = device->CC_id; int CC_id = device->CC_id;
int subframe; int subframe;
int sample_count=0; int sample_count=0;
*ptimestamp = sim.last_ru_rx_timestamp[ru_id][CC_id]; *ptimestamp = sim.last_ru_rx_timestamp[ru_id][CC_id];
LOG_D(SIM,"RU_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps, LOG_D(SIM,"RU_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
(unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id], (unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id],
(unsigned long long)sim.last_ru_rx_timestamp[ru_id][CC_id], (unsigned long long)sim.last_ru_rx_timestamp[ru_id][CC_id],
...@@ -187,9 +169,8 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -187,9 +169,8 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
usleep(500); usleep(500);
} }
subframe = (sim.last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms.samples_per_tti)%10; subframe = (sim.last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms.samples_per_tti)%10;
if (subframe_select(&RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms.frame_type == FDD) { if (subframe_select(&RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms.frame_type == FDD) {
LOG_D(SIM,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n", LOG_D(SIM,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
subframe,(unsigned long long)*ptimestamp, subframe,(unsigned long long)*ptimestamp,
...@@ -204,27 +185,23 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -204,27 +185,23 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
CC_id); CC_id);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,0);
} }
sim.last_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti; sim.last_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti;
sample_count += RC.ru[ru_id]->frame_parms.samples_per_tti; sample_count += RC.ru[ru_id]->frame_parms.samples_per_tti;
} }
return(nsamps); return(nsamps);
} }
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) {
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,1);
int UE_id = device->Mod_id; int UE_id = device->Mod_id;
int CC_id = device->CC_id; int CC_id = device->CC_id;
int subframe; int subframe;
int sample_count=0; int sample_count=0;
int read_size; int read_size;
int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti; int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
*ptimestamp = sim.last_UE_rx_timestamp[UE_id][CC_id]; *ptimestamp = sim.last_UE_rx_timestamp[UE_id][CC_id];
LOG_D(PHY,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n", LOG_D(PHY,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n",
UE_id, UE_id,
nsamps, nsamps,
...@@ -233,7 +210,6 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -233,7 +210,6 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti), (int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti),
cc); cc);
if (nsamps < sptti) if (nsamps < sptti)
read_size = nsamps; read_size = nsamps;
else else
...@@ -241,33 +217,28 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -241,33 +217,28 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
while (sample_count<nsamps) { while (sample_count<nsamps) {
LOG_D(SIM,"UE %d: DL simulation 1: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]); LOG_D(SIM,"UE %d: DL simulation 1: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
while (sim.current_UE_rx_timestamp[UE_id][CC_id] < while (sim.current_UE_rx_timestamp[UE_id][CC_id] <
(sim.last_UE_rx_timestamp[UE_id][CC_id]+read_size)) { (sim.last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
LOG_D(SIM,"UE %d: DL simulation 2: UE_trx_read : current TS %"PRIi64", last TS %"PRIi64", sleeping\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]); LOG_D(SIM,"UE %d: DL simulation 2: UE_trx_read : current TS %"PRIi64", last TS %"PRIi64", sleeping\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
usleep(500); usleep(500);
} }
LOG_D(SIM,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
LOG_D(SIM,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
// if we cross a subframe-boundary // if we cross a subframe-boundary
subframe = (sim.last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10; subframe = (sim.last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10;
// tell top-level we are busy // tell top-level we are busy
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
sim.subframe_UE_mask|=(1<<UE_id); sim.subframe_UE_mask|=(1<<UE_id);
LOG_D(SIM,"Setting UE_id %d mask to busy (%d)\n",UE_id,sim.subframe_UE_mask); LOG_D(SIM,"Setting UE_id %d mask to busy (%d)\n",UE_id,sim.subframe_UE_mask);
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
LOG_D(PHY,"UE %d: DL simulation 4: UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu,nsamps %d)\n", LOG_D(PHY,"UE %d: DL simulation 4: UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu,nsamps %d)\n",
UE_id,subframe,(unsigned long long)*ptimestamp, UE_id,subframe,(unsigned long long)*ptimestamp,
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id], (unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
nsamps); nsamps);
LOG_D(SIM,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n", LOG_D(SIM,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n",
UE_id,nsamps,subframe, UE_id,nsamps,subframe,
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti)); (int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti));
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,1);
do_DL_sig(&sim, do_DL_sig(&sim,
subframe, subframe,
...@@ -283,13 +254,8 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -283,13 +254,8 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
sim.last_UE_rx_timestamp[UE_id][CC_id], sim.last_UE_rx_timestamp[UE_id][CC_id],
(int)((sim.last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023), (int)((sim.last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
subframe); subframe);
sim.last_UE_rx_timestamp[UE_id][CC_id] += read_size; sim.last_UE_rx_timestamp[UE_id][CC_id] += read_size;
sample_count += read_size; sample_count += read_size;
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,0);
...@@ -298,51 +264,45 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** ...@@ -298,51 +264,45 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
int ru_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { int ru_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
int ru_id = device->Mod_id; int ru_id = device->Mod_id;
LTE_DL_FRAME_PARMS *frame_parms = &RC.ru[ru_id]->frame_parms; LTE_DL_FRAME_PARMS *frame_parms = &RC.ru[ru_id]->frame_parms;
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
LOG_D(SIM,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,sim.subframe_ru_mask); LOG_D(SIM,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,sim.subframe_ru_mask);
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
// compute amplitude of TX signal from first symbol in subframe // compute amplitude of TX signal from first symbol in subframe
// note: assumes that the packet is an entire subframe // note: assumes that the packet is an entire subframe
sim.ru_amp[ru_id] = 0; sim.ru_amp[ru_id] = 0;
for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) { for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) {
sim.ru_amp[ru_id] += (double)signal_energy((int32_t*)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL); sim.ru_amp[ru_id] += (double)signal_energy((int32_t *)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL);
} }
sim.ru_amp[ru_id] = sqrt(sim.ru_amp[ru_id]);
LOG_D(PHY,"Setting amp for RU %d to %f (%d)\n",ru_id,sim.ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t*)buff[0],frame_parms->ofdm_symbol_size))); sim.ru_amp[ru_id] = sqrt(sim.ru_amp[ru_id]);
LOG_D(PHY,"Setting amp for RU %d to %f (%d)\n",ru_id,sim.ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t *)buff[0],frame_parms->ofdm_symbol_size)));
// tell top-level we are done // tell top-level we are done
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
sim.subframe_ru_mask|=(1<<ru_id); sim.subframe_ru_mask|=(1<<ru_id);
LOG_D(SIM,"Setting RU %d to busy\n",ru_id); LOG_D(SIM,"Setting RU %d to busy\n",ru_id);
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
return(nsamps); return(nsamps);
} }
int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
return(nsamps); return(nsamps);
} }
void init_ru_devices(){ void init_ru_devices() {
module_id_t ru_id; module_id_t ru_id;
RU_t *ru; RU_t *ru;
// allocate memory for RU if not already done // allocate memory for RU if not already done
if (RC.ru==NULL) RC.ru = (RU_t**)malloc(RC.nb_RU*sizeof(RU_t*)); if (RC.ru==NULL) RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
for (ru_id=0;ru_id<RC.nb_RU;ru_id++) { for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
LOG_D(SIM,"Initiaizing rfdevice for RU %d\n",ru_id); LOG_D(SIM,"Initiaizing rfdevice for RU %d\n",ru_id);
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t*)malloc(sizeof(RU_t));
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t *)malloc(sizeof(RU_t));
ru = RC.ru[ru_id]; ru = RC.ru[ru_id];
ru->rfdevice.Mod_id = ru_id; ru->rfdevice.Mod_id = ru_id;
ru->rfdevice.CC_id = 0; ru->rfdevice.CC_id = 0;
...@@ -354,12 +314,10 @@ void init_ru_devices(){ ...@@ -354,12 +314,10 @@ void init_ru_devices(){
ru->rfdevice.trx_set_freq_func = ru_trx_set_freq; ru->rfdevice.trx_set_freq_func = ru_trx_set_freq;
ru->rfdevice.trx_set_gains_func = ru_trx_set_gains; ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
sim.last_ru_rx_timestamp[ru_id][0] = 0; sim.last_ru_rx_timestamp[ru_id][0] = 0;
} }
} }
void init_ue_devices(PHY_VARS_UE *UE) { void init_ue_devices(PHY_VARS_UE *UE) {
AssertFatal(UE!=NULL,"UE context is not allocated\n"); AssertFatal(UE!=NULL,"UE context is not allocated\n");
printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id); printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id);
UE->rfdevice.Mod_id = UE->Mod_id; UE->rfdevice.Mod_id = UE->Mod_id;
...@@ -374,23 +332,21 @@ void init_ue_devices(PHY_VARS_UE *UE) { ...@@ -374,23 +332,21 @@ void init_ue_devices(PHY_VARS_UE *UE) {
sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0; sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0;
} }
void init_ocm(double snr_dB,double sinr_dB) void init_ocm(void) {
{
module_id_t UE_id, ru_id; module_id_t UE_id, ru_id;
int CC_id; int CC_id;
randominit(0); randominit(0);
set_taus_seed(0); set_taus_seed(0);
init_channelmod();
double snr_dB = channelmod_get_snr_dB();
double sinr_dB = channelmod_get_sinr_dB();
init_channel_vars ();//fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0); init_channel_vars ();//fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0);
// initialize channel descriptors // initialize channel descriptors
LOG_I(PHY,"Initializing channel descriptors (nb_RU %d, nb_UE %d)\n",RC.nb_RU,NB_UE_INST); LOG_I(PHY,"Initializing channel descriptors (nb_RU %d, nb_UE %d)\n",RC.nb_RU,NB_UE_INST);
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) { for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) { for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
LOG_I(PHY,"Initializing channel descriptors (RU %d, UE %d) for N_RB_DL %d\n",ru_id,UE_id, LOG_I(PHY,"Initializing channel descriptors (RU %d, UE %d) for N_RB_DL %d\n",ru_id,UE_id,
RC.ru[ru_id]->frame_parms.N_RB_DL); RC.ru[ru_id]->frame_parms.N_RB_DL);
sim.RU2UE[ru_id][UE_id][CC_id] = sim.RU2UE[ru_id][UE_id][CC_id] =
...@@ -404,8 +360,6 @@ void init_ocm(double snr_dB,double sinr_dB) ...@@ -404,8 +360,6 @@ void init_ocm(double snr_dB,double sinr_dB)
0); 0);
random_channel(sim.RU2UE[ru_id][UE_id][CC_id],0); random_channel(sim.RU2UE[ru_id][UE_id][CC_id],0);
LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN",UE_id, ru_id); LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN",UE_id, ru_id);
sim.UE2RU[UE_id][ru_id][CC_id] = sim.UE2RU[UE_id][ru_id][CC_id] =
new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx, new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
RC.ru[ru_id]->nb_rx, RC.ru[ru_id]->nb_rx,
...@@ -415,14 +369,12 @@ void init_ocm(double snr_dB,double sinr_dB) ...@@ -415,14 +369,12 @@ void init_ocm(double snr_dB,double sinr_dB)
0.0, 0.0,
0, 0,
0); 0);
random_channel(sim.UE2RU[UE_id][ru_id][CC_id],0); random_channel(sim.UE2RU[UE_id][ru_id][CC_id],0);
// to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed. // to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed.
//UE2RU[UE_id][ru_id] = RU2UE[ru_id][UE_id]; //UE2RU[UE_id][ru_id] = RU2UE[ru_id][UE_id];
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id); AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id); AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
if (ru_id == (UE_id % RC.nb_RU)) { if (ru_id == (UE_id % RC.nb_RU)) {
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower; sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
...@@ -435,26 +387,22 @@ void init_ocm(double snr_dB,double sinr_dB) ...@@ -435,26 +387,22 @@ void init_ocm(double snr_dB,double sinr_dB)
LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id, LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB, sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB); RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB);
} }
} }
} }
} }
void update_ocm(double snr_dB,double sinr_dB) void update_ocm(double snr_dB,double sinr_dB) {
{
module_id_t UE_id, ru_id; module_id_t UE_id, ru_id;
int CC_id; int CC_id;
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) { for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) { for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id); AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id); AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
if (ru_id == (UE_id % RC.nb_RU)) { if (ru_id == (UE_id % RC.nb_RU)) {
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower; sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
...@@ -467,58 +415,50 @@ void update_ocm(double snr_dB,double sinr_dB) ...@@ -467,58 +415,50 @@ void update_ocm(double snr_dB,double sinr_dB)
LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id, LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB, sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB); RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB);
} }
} }
} }
} }
void init_channel_vars(void) void init_channel_vars(void) {
{
int i; int i;
memset(sim.RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX); memset(sim.RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX);
for (i=0;i<NB_UE_INST;i++)
for (i=0; i<NB_UE_INST; i++)
pthread_mutex_init(&sim.RU_output_mutex[i],NULL); pthread_mutex_init(&sim.RU_output_mutex[i],NULL);
memset(sim.UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX); memset(sim.UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX);
for (i=0;i<RC.nb_RU;i++)
pthread_mutex_init(&sim.UE_output_mutex[i],NULL);
for (i=0; i<RC.nb_RU; i++)
pthread_mutex_init(&sim.UE_output_mutex[i],NULL);
} }
void *rfsim_top(void *n_frames) { void *rfsim_top(void *n_frames) {
wait_sync("rfsim_top"); wait_sync("rfsim_top");
printf("Running rfsim with %d frames\n",*(int *)n_frames);
printf("Running rfsim with %d frames\n",*(int*)n_frames);
for (int frame = 0; for (int frame = 0;
frame < *(int*)n_frames; frame < *(int *)n_frames;
frame++) { frame++) {
for (int sf = 0; sf < 10; sf++) { for (int sf = 0; sf < 10; sf++) {
int CC_id=0; int CC_id=0;
int all_done=0; int all_done=0;
while (all_done==0) {
while (all_done==0) {
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
int subframe_ru_mask_local = (subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? sim.subframe_ru_mask : ((1<<RC.nb_RU)-1); int subframe_ru_mask_local = (subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? sim.subframe_ru_mask : ((1<<RC.nb_RU)-1);
int subframe_UE_mask_local = (RC.ru[0]->frame_parms.frame_type == FDD || subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_DL) ? sim.subframe_UE_mask : ((1<<NB_UE_INST)-1); int subframe_UE_mask_local = (RC.ru[0]->frame_parms.frame_type == FDD || subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_DL) ? sim.subframe_UE_mask : ((1<<NB_UE_INST)-1);
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
LOG_D(SIM,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,RC.nb_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local); LOG_D(SIM,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,RC.nb_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) && if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) &&
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1; (subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
else usleep(1500); else usleep(1500);
} }
//clear subframe masks for next round //clear subframe masks for next round
pthread_mutex_lock(&sim.subframe_mutex); pthread_mutex_lock(&sim.subframe_mutex);
sim.subframe_ru_mask=0; sim.subframe_ru_mask=0;
...@@ -526,17 +466,19 @@ void *rfsim_top(void *n_frames) { ...@@ -526,17 +466,19 @@ void *rfsim_top(void *n_frames) {
pthread_mutex_unlock(&sim.subframe_mutex); pthread_mutex_unlock(&sim.subframe_mutex);
// increment timestamps // increment timestamps
for (int ru_id=0;ru_id<RC.nb_RU;ru_id++) { for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) {
sim.current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti; sim.current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti;
LOG_D(SIM,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,sim.current_ru_rx_timestamp[ru_id][CC_id]); LOG_D(SIM,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,sim.current_ru_rx_timestamp[ru_id][CC_id]);
} }
for (int UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
for (int UE_inst = 0; UE_inst<NB_UE_INST; UE_inst++) {
sim.current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti; sim.current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
LOG_D(SIM,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,sim.current_UE_rx_timestamp[UE_inst][CC_id]); LOG_D(SIM,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,sim.current_UE_rx_timestamp[UE_inst][CC_id]);
} }
if (oai_exit == 1) return((void*)NULL);
if (oai_exit == 1) return((void *)NULL);
} }
} }
return((void*)NULL); return((void *)NULL);
} }
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "PHY/defs_UE.h" #include "PHY/defs_UE.h"
#include "PHY/defs_eNB.h" #include "PHY/defs_eNB.h"
void init_ocm(double snr_dB,double sinr_dB); void init_ocm(void);
void update_ocm(double snr_dB,double sinr_dB); void update_ocm(double snr_dB,double sinr_dB);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment