Linux CSI Tool 完整使用说明(权威版 已成功测试)

本文涉及到的所有文件均在以下百度网盘链接的压缩包内,请大家自取
链接: https://pan.baidu.com/s/1I67ex4KwFnItlyFCoWlQoQ
提取码: ep8b

相关链接:

1. 硬件设备

  1. 电脑设备推荐ThinkPad X201,推荐购买链接:https://item.taobao.com/item.htm?_u=v3mfohc203a6&id=575205451871
  2. 网卡务必使用Intel 5300网卡,推荐购买链接(附赠天线):https://item.taobao.com/item.htm?spm=a1z09.2.0.0.48192e8dEszrp2&id=572509799776&_u=v3mfohc2b41c

2. 刷BIOS & 拆卸替换网卡

由于ThinkPad X201电脑的BIOS版本比较旧,因此我之前直接换装网卡之后在BIOS启动阶段就出错了,提示无法识别的硬件设备。因此我们需要在换装网卡之前利用Win PE系统刷一遍BIOS。

  1. 准备一个2G左右的U盘,准备PE系统的安装程序:WePE_32_V2.1.exe(压缩包内)

  2. 运行该程序,根据程序的指示将U盘刷成PE系统的启动盘。

  3. 准备 ThinkPad X201 的 BIOS 包:ThinkPad X201_6quj10us_SLIC21_no_whitelist.zip(压缩包内)

  4. 将BIOS包复制到U盘名为“微软PE工具箱”的分区内。

  5. 接下来将U盘插入ThinkPad X201内,启动电源,在出现初始化界面时按ThinkVantage按钮,然后出现选择菜单时按F12,在启动菜单中选择U盘。

  6. 等待进入U盘PE系统,在“微软PE工具箱”分区内解压之前下载的BIOS包,建议选择64位的文件夹(如果64bit刷BIOS失败了用32bit也行),然后双击“WinPhlash64.exe”运行,直接点击flash bios即可。

  7. 等待刷机完成后关闭电脑,接下来是拆卸和换装网卡步骤。

  8. 切断笔记本电源,拔出笔记本电池,切勿带电操作!

  9. 用十字螺丝刀拧开笔记本背面的螺丝(拧开带有键盘、触摸板图标的螺丝即可)

  10. 拧完螺丝后轻轻就可以拆开笔记本的键盘和触摸板。

  11. 原先的网卡在右下方的位置,我们需要用螺丝刀拧开螺丝后才能移除原有网卡,然后才能插入5300网卡。

  12. 由于一般天线是放在笔记本外侧的,所以需要拆除右下方的声卡板来为接线提供空间。

  13. 安装完毕后如下图所示:
    在这里插入图片描述

3. 操作系统

操作系统推荐Ubuntu 14.06 LTS,内核版本为3.13,不过现在好像只能下载到4.4的内核版本(镜像链接:https://mirrors.zju.edu.cn/ubuntu-releases/

我用的是3.13内核版本的Ubuntu 14.06,问题应该不大,因为后面要重新编译过内核。

怎么安装系统就不说了。相信大家都没有问题。

另外,如果你能在安装系统的界面成功检测到周围的WIFI并且能连接成功,那说明你的BIOS刷机成功了,系统“认识”这款网卡。

不过还是建议大家在连着有线网的情况下安装,包括后续的安装操作。

4. 内核编译、驱动、固件配置

操作系统安装完毕后,重启进入。刚进入系统时可能会提示你是否要升级到16.04,点击否就行了。包括提示要更新软件等都略过吧。

  1. 安装相关依赖

    • 更新源

      sudo apt-get update
      
    • 下载安装依赖包

      sudo apt-get -y install git-core kernel-package fakeroot build-essential ncurses-dev
      sudo apt-get -y install libnl-dev libssl-dev
      sudo apt-get -y install iw
      
  2. 下载、编译内核

    • 准备 intel-5300-csi-github-master.tar.gz

      压缩包内有:intel-5300-csi-github-master.tar.gz,如果觉得百度网盘下载速度慢,这里提供一位博主的:https://download.csdn.net/download/u014645508/10579514

    • 解压、编译

      按顺序一步一步在终端执行以下代码

      cd ~
      tar -xvf intel-5300-csi-github-master.tar.gz
      cd intel-5300-csi-github-master
      make oldconfig # 一直按回车
      make menuconfig # 在弹出的窗口选择Save,再Exit,一定要save一遍,而不是直接退出。另外可能会因为终端窗口比较小无法显示完全而报错
      make -j4 # 编译内核一直都比较慢,大概半小时到一小时
      sudo make install modules_install # 安装kernel module,大约15分钟
      sudo make install
      sudo make install modules_install # 再次安装内核模块(保险起见,一定要执行)
      sudo mkinitramfs -o /boot/initrd.img-`cat include/config/kernel.release` `cat include/config/kernel.release`
      make headers_install
      sudo mkdir /usr/src/linux-headers-`cat include/config/kernel.release`
      sudo cp -rf usr/include /usr/src/linux-headers-`cat include/config/kernel.release`/include
      
    • 添加刚刚编译过的内核(4.2.0版本)至启动项

      cd /etc/default
      sudo vi grub
      

      注释这一行

      GRUB_HIDDEN_TIMEOUT=0
      
    • 更新grub

      sudo update-grub
      
    • 重启电脑,一定要在启动选项中选择4.2的内核版本进入。

  3. 替换固件

    按顺序在终端执行以下代码

    cd ~
    git clone https://github.com/dhalperi/linux-80211n-csitool-supplementary.git
    for file in /lib/firmware/iwlwifi-5000-*.ucode; do sudo mv $file $file.orig; done
    sudo cp linux-80211n-csitool-supplementary/firmware/iwlwifi-5000-2.ucode.sigcomm2010 /lib/firmware/
    sudo ln -s iwlwifi-5000-2.ucode.sigcomm2010 /lib/firmware/iwlwifi-5000-2.ucode
    

    到此,5300网卡的驱动以及CSI收发包工具都已经配置完毕。接下来分别介绍发包和收包的操作。

5. 具体使用

5.1 共同准备

在终端按顺序执行以下代码

cd ~
sudo apt-get install libpcap-dev
git clone https://github.com/dhalperi/lorcon-old.git
cd lorcon-old
./configure
make
sudo make install

5.2 CSI发送端

  1. 编译发送代码

    cd ~
    cd linux-80211n-csitool-supplementary/injection/
    make
    
  2. 执行初始化脚本 inject.sh(压缩包内:inject.sh)

    在执行之前建议先查看无线网卡接口名称,一般情况下是 wlan0

    iwconfig
    

    如图所示:
    在这里插入图片描述
    执行脚本即参数配置:

    sudo bash ./inject.sh wlan0 64 HT20
    

    参数解释:第一个参数是无线网卡接口名称,一般是wlan0,第二个参数是信道编号,建议64,第三个是OFDM下的HT20模式

    inject.sh代码:

    #!/usr/bin/sudo /bin/bash
    sudo service network-manager stop
    WLAN_INTERFACE=$1
    SLEEP_TIME=2
    modprobe iwlwifi debug=0x40000
    if [ "$#" -ne 3 ]; then
        echo "Going to use default settings!"
        chn=64
        bw=HT20
    else
        chn=$2
        bw=$3
    fi
    sleep $SLEEP_TIME
    ifconfig $WLAN_INTERFACE 2>/dev/null 1>/dev/null
    while [ $? -ne 0 ]
    do
        ifconfig $WLAN_INTERFACE 2>/dev/null 1>/dev/null
    done
    sleep $SLEEP_TIME
    echo "Add monitor mon0....."
    iw dev $WLAN_INTERFACE interface add mon0 type monitor
    sleep $SLEEP_TIME
    echo "Bringing $WLAN_INTERFACE down....."
    ifconfig $WLAN_INTERFACE down
    while [ $? -ne 0 ]
    do
        ifconfig $WLAN_INTERFACE down
    done
    sleep $SLEEP_TIME
    echo "Bringing mon0 up....."
    ifconfig mon0 up
    while [ $? -ne 0 ]
    do
        ifconfig mon0 up
    done
    sleep $SLEEP_TIME
    echo "Set channel $chn $bw....."
    iw mon0 set channel $chn $bw
    
  3. 发送数据

    echo 0x1c113 | sudo tee `sudo find /sys -name monitor_tx_rate`
    cd ~
    cd linux-80211n-csitool-supplementary/injection/
    sudo ./random_packets 1000000000 100 1 1000
    

    第一行的参数配置如果有个人需求可以参考:CSI Tool安装使用讲解

    不过个人建议就这样就行了,毕竟这个工具搭建很麻烦。

    random_packets的参数解释:第一个参数是累计发包数量,第二个参数是包的大小,第三个参数1代表injection MAC,用1就可以了,最后一个参数代表每隔1000微秒发一次包,即一秒发1000个包。

5.3 CSI接收端

  1. 编译接收代码

    cd ~
    cd linux-80211n-csitool-supplementary/netlink/
    make
    
  2. 执行初始化脚本 monitor.sh (压缩包内:monitor.sh)

    注意:一定要采用这个脚本,其他博客上的脚本基本缺少了第2、3行内容,否则收不到包的!我尝试了好几次,才找到办法。如果发现此脚本运行后提示找不到对应的wlan接口也可尝试另外一个,感谢粉丝“qq_45884215”提供的资源

    sudo bash ./monitor.sh wlan0 64 HT20
    

    信道编号要和发送端的一样

    monitor.sh代码

    #!/usr/bin/sudo /bin/bash
    sudo modprobe -r iwlwifi mac80211
    sudo modprobe iwlwifi connector_log=0x1
    
    sudo service network-manager stop
    SLEEP_TIME=2
    WLAN_INTERFACE=$1
    if [ "$#" -ne 3 ]; then
    	echo "Going to use default settings!"
    	chn=64
    	bw=HT20
    else
    	chn=$2
    	bw=$3
    fi
    echo "Bringing $WLAN_INTERFACE down......"
    ifconfig $WLANINTERFACE down
    while [ $? -ne 0 ]
    do
    	ifconfig $WLAN_INTERFACE down
    done
    sleep $SLEEP_TIME
    echo "Set $WLAN_INTERFACE into monitor mode......"
    iwconfig $WLAN_INTERFACE mode monitor
    while [ $? -ne 0 ]
    do
    	iwconfig $WLAN_INTERFACE mode monitor
    done
    sleep $SLEEP_TIME
    echo "Bringing $WLAN_INTERFACE up......"
    ifconfig $WLAN_INTERFACE up
    while [ $? -ne 0 ]
    do
    	ifconfig $WLAN_INTERFACE up
    done
    sleep $SLEEP_TIME
    echo "Set channel $chn $bw..."
    iw $WLAN_INTERFACE set channel $chn $bw
    

monitor.sh 备用代码
请添加图片描述

  1. 执行收包程序

    cd ~
    cd linux-80211n-csitool-supplementary/netlink/
    sudo ./log_to_file temp # temp是保存数据的文件名,强烈建议文件名改为dat后缀
    

    由于原生的代码只能不停的收包,因此我编写了一个可以收包n秒以后自动停止的C代码(压缩包内:log_to_file.c):

    使用方法如下:

    cd ~
    cd linux-80211n-csitool-supplementary/netlink/
    sudo ./log_to_file temp 3
    

    参数解释:temp是保存数据的文件名,3代表从检测到CSI包之后收3秒,然后退出程序。如果发送端每秒发送1000个包,那么在不丢包的情况下可以收到3000个包。如下图:
    在这里插入图片描述

    log_to_file.c 文件代码:

    /*
     * (c) 2008-2011 Daniel Halperin <dhalperi@cs.washington.edu>
     */
    #include "iwl_connector.h"
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <signal.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <linux/netlink.h>
    
    #define MAX_PAYLOAD 2048
    #define SLOW_MSG_CNT 100
    
    int sock_fd = -1; // the socket
    FILE *out = NULL;
    
    void check_usage(int argc, char **argv);
    
    FILE *open_file(char *filename, char *spec);
    
    void caught_signal(int sig);
    
    void exit_program(int code);
    void exit_program_err(int code, char *func);
    void exit_program_with_alarm(int sig);
    
    int main(int argc, char **argv)
    {
    	/* Local variables */
    	struct sockaddr_nl proc_addr, kern_addr; // addrs for recv, send, bind
    	struct cn_msg *cmsg;
    	char buf[4096];
    	int ret;
    	unsigned short l, l2;
    	int count = 0;
    
    	/* Initialize signal*/
    	signal(SIGALRM, exit_program_with_alarm);
    
    	/* Make sure usage is correct */
    	check_usage(argc, argv);
    
    	/* Open and check log file */
    	out = open_file(argv[1], "w");
    
    	/* Setup the socket */
    	sock_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
    	if (sock_fd == -1)
    		exit_program_err(-1, "socket");
    
    	/* Initialize the address structs */
    	memset(&proc_addr, 0, sizeof(struct sockaddr_nl));
    	proc_addr.nl_family = AF_NETLINK;
    	proc_addr.nl_pid = getpid(); // this process' PID
    	proc_addr.nl_groups = CN_IDX_IWLAGN;
    	memset(&kern_addr, 0, sizeof(struct sockaddr_nl));
    	kern_addr.nl_family = AF_NETLINK;
    	kern_addr.nl_pid = 0; // kernel
    	kern_addr.nl_groups = CN_IDX_IWLAGN;
    
    	/* Now bind the socket */
    	if (bind(sock_fd, (struct sockaddr *)&proc_addr, sizeof(struct sockaddr_nl)) == -1)
    		exit_program_err(-1, "bind");
    
    	/* And subscribe to netlink group */
    	{
    		int on = proc_addr.nl_groups;
    		ret = setsockopt(sock_fd, 270, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
    		if (ret)
    			exit_program_err(-1, "setsockopt");
    	}
    
    	/* Set up the "caught_signal" function as this program's sig handler */
    	signal(SIGINT, caught_signal);
    
    	/* Poll socket forever waiting for a message */
    	while (1)
    	{
    		/* Receive from socket with infinite timeout */
    		ret = recv(sock_fd, buf, sizeof(buf), 0);
    		if (ret == -1)
    			exit_program_err(-1, "recv");
    		/* Pull out the message portion and print some stats */
    		cmsg = NLMSG_DATA(buf);
    		if (count % SLOW_MSG_CNT == 0)
    			printf("received %d bytes: counts: %d id: %d val: %d seq: %d clen: %d\n", cmsg->len, count, cmsg->id.idx, cmsg->id.val, cmsg->seq, cmsg->len);
    		/* Log the data to file */
    		l = (unsigned short)cmsg->len;
    		l2 = htons(l);
    		fwrite(&l2, 1, sizeof(unsigned short), out);
    		ret = fwrite(cmsg->data, 1, l, out);
    		++count;
    		if (count == 1)
    		{
    			/* Set alarm */
    			alarm((*argv[2] - '0'));
    		}
    		if (ret != l)
    			exit_program_err(1, "fwrite");
    	}
    
    	exit_program(0);
    	return 0;
    }
    
    void check_usage(int argc, char **argv)
    {
    	if (argc != 3)
    	{
    		fprintf(stderr, "Usage: %s <output_file> <time>\n", argv[0]);
    		exit_program(1);
    	}
    }
    
    FILE *open_file(char *filename, char *spec)
    {
    	FILE *fp = fopen(filename, spec);
    	if (!fp)
    	{
    		perror("fopen");
    		exit_program(1);
    	}
    	return fp;
    }
    
    void caught_signal(int sig)
    {
    	fprintf(stderr, "Caught signal %d\n", sig);
    	exit_program(0);
    }
    
    void exit_program(int code)
    {
    	if (out)
    	{
    		fclose(out);
    		out = NULL;
    	}
    	if (sock_fd != -1)
    	{
    		close(sock_fd);
    		sock_fd = -1;
    	}
    	exit(code);
    }
    
    void exit_program_err(int code, char *func)
    {
    	perror(func);
    	exit_program(code);
    }
    
    void exit_program_with_alarm(int sig)
    {
    	exit_program(0);
    }
    

6. CSI数据处理(Matlab & Python)

Matlab和Python都可以对数据进行处理。个人推荐Matlab,更权威,Python的处理结果貌似和Matlab不一样。

这两种方式都可以将dat格式的原数据转化为csv格式。因为我采用的收发都是3根天线,每根天线都有30个子载波,一秒钟3000个包,所以最后csv的数据维度是3000 * (30 * 3 * 3)即3000 * 270的大小。

6.1 Matlab方式

  1. 下载Matlab处理dat文件的代码包。(压缩包内:01 dat_to_csi_mat.zip)

  2. 运行代码包内的data_to_csi.m脚本。

    data_to_csi.m:

    csi_file = read_bf_file('temp.dat');
    row = size(csi_file, 1);
    temp = [];
    
    for k = 1:row
        csi = get_scaled_csi(csi_file{k});
        csi = csi(:)';
    
        for m = 1:length(csi)
            csi(m) = abs(csi(m));
        end
    
        temp = [temp; csi];
    end
    
    writematrix(temp, 'output.csv');
    

6.2 Python方式

直接运行以下Python代码,注意文件路径等参数修改为自己的

import numpy as np
import math


class Bfee:

    def __init__(self):
        pass

    @staticmethod
    def from_file(filename, model_name_encode="shift-JIS"):

        with open(filename, "rb") as f:
            from functools import reduce
            # reduce(函数,list),将list中元素依次累加
            array = bytes(reduce(lambda x, y: x+y, list(f)))

        bfee = Bfee()

#         vmd.current_index = 0
        bfee.file_len = len(array)
        bfee.dicts = []
        bfee.all_csi = []

#         vmd.timestamp_low0 = int.from_bytes(array[3:7], byteorder='little', signed=False)

#         array = array[3:]

        # %% Initialize variables
        # ret = cell(ceil(len/95),1);    # % Holds the return values - 1x1 CSI is 95 bytes big, so this should be upper bound
        cur = 0                       # % Current offset into file
        count = 0                    # % Number of records output
        broken_perm = 0              # % Flag marking whether we've encountered a broken CSI yet
        # % What perm should sum to for 1,2,3 antennas
        triangle = [0, 1, 3]

        while cur < (bfee.file_len - 3):
            # % Read size and code
            # % 将文件数据读取到维度为 sizeA 的数组 A 中,并将文件指针定位到最后读取的值之后。fread 按列顺序填充 A。
            bfee.field_len = int.from_bytes(
                array[cur:cur+2], byteorder='big', signed=False)
            bfee.code = array[cur+2]
            cur = cur+3

            # there is CSI in field if code == 187,If unhandled code skip (seek over) the record and continue
            if bfee.code == 187:
                pass
            else:
                # % skip all other info
                cur = cur + bfee.field_len - 1
                continue

            # get beamforming or phy data
            if bfee.code == 187:
                count = count + 1

                bfee.timestamp_low = int.from_bytes(
                    array[cur:cur+4], byteorder='little', signed=False)
                bfee.bfee_count = int.from_bytes(
                    array[cur+4:cur+6], byteorder='little', signed=False)
                bfee.Nrx = array[cur+8]
                bfee.Ntx = array[cur+9]
                bfee.rssi_a = array[cur+10]
                bfee.rssi_b = array[cur+11]
                bfee.rssi_c = array[cur+12]
                bfee.noise = array[cur+13] - 256
                bfee.agc = array[cur+14]
                bfee.antenna_sel = array[cur+15]
                bfee.len = int.from_bytes(
                    array[cur+16:cur+18], byteorder='little', signed=False)
                bfee.fake_rate_n_flags = int.from_bytes(
                    array[cur+18:cur+20], byteorder='little', signed=False)
                bfee.calc_len = (
                    30 * (bfee.Nrx * bfee.Ntx * 8 * 2 + 3) + 6) / 8
                bfee.csi = np.zeros(
                    shape=(30, bfee.Nrx, bfee.Ntx), dtype=np.dtype(np.complex))
                bfee.perm = [1, 2, 3]
                bfee.perm[0] = ((bfee.antenna_sel) & 0x3)
                bfee.perm[1] = ((bfee.antenna_sel >> 2) & 0x3)
                bfee.perm[2] = ((bfee.antenna_sel >> 4) & 0x3)

                cur = cur + 20

                # get payload
                payload = array[cur:cur+bfee.len]
                cur = cur + bfee.len

                index = 0

                # Check that length matches what it should
                if (bfee.len != bfee.calc_len):
                    print("MIMOToolbox:read_bfee_new:size",
                          "Wrong beamforming matrix size.")

                # Compute CSI from all this crap :
                # import struct
                for i in range(30):
                    index += 3
                    remainder = index % 8
                    for j in range(bfee.Nrx):
                        for k in range(bfee.Ntx):
                            real_bin = bytes([(payload[int(index / 8)] >> remainder) | (
                                payload[int(index/8+1)] << (8-remainder)) & 0b11111111])
                            real = int.from_bytes(
                                real_bin, byteorder='little', signed=True)
                            imag_bin = bytes([(payload[int(index / 8+1)] >> remainder) | (
                                payload[int(index/8+2)] << (8-remainder)) & 0b11111111])
                            imag = int.from_bytes(
                                imag_bin, byteorder='little', signed=True)
                            tmp = np.complex(float(real), float(imag))
                            bfee.csi[i, j, k] = tmp
                            index += 16

                # % matrix does not contain default values
                if sum(bfee.perm) != triangle[bfee.Nrx-1]:
                    print('WARN ONCE: Found CSI (', filename, ') with Nrx=',
                          bfee.Nrx, ' and invalid perm=[', bfee.perm, ']\n')
                else:
                    temp_csi = np.zeros(
                        bfee.csi.shape, dtype=np.dtype(np.complex))
                    # bfee.csi[:,bfee.perm[0:bfee.Nrx],:] = bfee.csi[:,0:bfee.Nrx,:]
                    for r in range(bfee.Nrx):
                        temp_csi[:, bfee.perm[r], :] = bfee.csi[:, r, :]
                    bfee.csi = temp_csi
                # 将类属性导出为dict,并返回
                bfee_dict = {}
                bfee_dict['timestamp_low'] = bfee.timestamp_low
                bfee_dict['bfee_count'] = bfee.bfee_count
                bfee_dict['Nrx'] = bfee.Nrx
                bfee_dict['Ntx'] = bfee.Ntx
                bfee_dict['rssi_a'] = bfee.rssi_a
                bfee_dict['rssi_b'] = bfee.rssi_b
                bfee_dict['rssi_c'] = bfee.rssi_c
                bfee_dict['noise'] = bfee.noise
                bfee_dict['agc'] = bfee.agc
                bfee_dict['antenna_sel'] = bfee.antenna_sel
                bfee_dict['perm'] = bfee.perm
                bfee_dict['len'] = bfee.len
                bfee_dict['fake_rate_n_flags'] = bfee.fake_rate_n_flags
                bfee_dict['calc_len'] = bfee.calc_len
                bfee_dict['csi'] = bfee.csi

                bfee.dicts.append(bfee_dict)
                bfee.all_csi.append(bfee.csi)

        return bfee


def db(X, U):
    R = 1
    if 'power'.startswith(U):
        assert X >= 0
    else:
        X = math.pow(abs(X), 2) / R

    return (10 * math.log10(X) + 300) - 300


def dbinv(x):
    return math.pow(10, x / 10)


def get_total_rss(csi_st):
    # Careful here: rssis could be zero
    rssi_mag = 0
    if csi_st['rssi_a'] != 0:
        rssi_mag = rssi_mag + dbinv(csi_st['rssi_a'])
    if csi_st['rssi_b'] != 0:
        rssi_mag = rssi_mag + dbinv(csi_st['rssi_b'])
    if csi_st['rssi_c'] != 0:
        rssi_mag = rssi_mag + dbinv(csi_st['rssi_c'])
    return db(rssi_mag, 'power') - 44 - csi_st['agc']


def get_scale_csi(csi_st):
    # Pull out csi
    csi = csi_st['csi']
    # print(csi.shape)
    # print(csi)
    # Calculate the scale factor between normalized CSI and RSSI (mW)
    csi_sq = np.multiply(csi, np.conj(csi)).real
    csi_pwr = np.sum(csi_sq, axis=0)
    csi_pwr = csi_pwr.reshape(1, csi_pwr.shape[0], -1)
    rssi_pwr = dbinv(get_total_rss(csi_st))

    scale = rssi_pwr / (csi_pwr / 30)

    if csi_st['noise'] == -127:
        noise_db = -92
    else:
        noise_db = csi_st['noise']
    thermal_noise_pwr = dbinv(noise_db)

    quant_error_pwr = scale * (csi_st['Nrx'] * csi_st['Ntx'])

    total_noise_pwr = thermal_noise_pwr + quant_error_pwr
    ret = csi * np.sqrt(scale / total_noise_pwr)
    if csi_st['Ntx'] == 2:
        ret = ret * math.sqrt(2)
    elif csi_st['Ntx'] == 3:
        ret = ret * math.sqrt(dbinv(4.5))
    return ret


written_data = ''

bfee = Bfee.from_file('temp.dat', model_name_encode="gb2312")
for k in range(len(bfee.all_csi)):
    csi = get_scale_csi(bfee.dicts[k])

    for a in range(30):
        for b in range(3):
            for c in range(3):
                temp = abs(csi[a][b][c])
                written_data += str(temp) + ','
    written_data = written_data[: len(written_data) - 1] + '\n'
written_data = written_data[: len(written_data) - 1]

file = open('output.csv', mode='w')
file.write(written_data)
file.close()
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐