Wi-Fi CSI Introduction
Wi-Fi CSI (Channel State Information) is a technology used to describe the characteristics of wireless channels. It aims to quantify the aggregate effect of wireless phenomena (such as interference, multipath, doppler shift…) on wireless signals in a given environment by reporting complete CSIs. And can be used in applications such as human activity analysis, WiFi indoor positioning, and gesture recognition.
Realtek Wi-Fi CSI is divided into Active CSI and Passive CSI schemes based on whether the Realtek device (STA mode or SoftAP mode) participates in transmitting the CSI triggering frames.
Active CSI: The Realtek device needs to actively transmit CSI triggering frames
Active CSI is divided into two modes based on the type of CSI triggering frame: unicast mode and broadcast mode. For details, refer to Active CSI: Unicast mode and Active CSI: Broadcast Mode.
Using Public Action frame as CSI triggering frame in Active CSI.
Passive CSI: The Realtek device is not required to transmit CSI triggering frames
Details refer to Passive CSI.
Active CSI: Unicast mode
METHOD1: A Realtek STA transmits a unicast CSI triggering frame to the AP and derives CSI from the ACK response to the previous CSI triggering frame (one-to-one communication).
METHOD1_Variant: A Realtek STA transmits a unicast CSI triggering frame to another STAx and derives CSI from the ACK response to the previous CSI triggering frame (one-to-many communication via polling).
METHOD2: A Realtek SoftAP transmits a unicast CSI triggering frame to associated stations and derives CSI from the ACK response to the previous unicast CSI triggering frame (one-to-many communication via polling).
Collect CSI from Rx ACK Packet in Rx Response Mode
Active CSI: Broadcast Mode
METHOD3: Realtek SoftAP transmits a broadcast CSI triggering frame, which are decoded by Realtek STAs to derive CSI.
METHOD4: A Realtek STA transmits a broadcast CSI triggering frame, which are decoded by neighboring Realtek STAs to derive CSI.
Collect CSI from Rx Broadcast Packet in Rx Normal Mode
Passive CSI
METHOD5: A Realtek STA/SoftAP derives CSI from received packets in Rx Normal Mode (one-to-one communication).
Collect CSI from Rx packet in Rx Normal Mode
Wi-Fi CSI Architecture
Wi-Fi CSI report mainly consists of three modules:
Configure and Enable Wi-Fi CSI
The APP must call the API to configure Wi-Fi CSI parameters as needed and enable the Wi-Fi CSI function.
The APP must call the API to disable the Wi-Fi CSI function when inactive.
Register/Deregister Wi-Fi CSI Callback
Register a Wi-Fi CSI callback function when enabling Wi-Fi CSI. The Wi-Fi driver will transmit a flag to notify the APP when each CSI packet ready through the callback function.
Release the Wi-Fi CSI callback function when disabling Wi-Fi CSI.
Report Wi-Fi CSI
The APP should run a separate thread to wait for the CSI report ready flag, then call the API to read the CSI report.
Wi-Fi CSI architecture
Wi-Fi CSI Releated APIs
wifi_csi_config
Function prototype:
int wifi_csi_config(struct _rtw_csi_action_parm_t *act_param)
Description: CSI parameter configuration and enable/disable
act =
CSI_ACT_CFG
to configure Wi-Fi CSI parametersact =
CSI_ACT_EN
to enable/disable Wi-Fi CSI. If disabled, the APP must reconfigure Wi-Fi CSI parameters before re-enabling Wi-Fi CSI.
Parameter Definitions
Parameter |
Type |
Description |
---|---|---|
group_num |
unsigned char |
Specify the CSI info subcarrier decimation
|
accuracy |
unsigned char |
Specify the CSI raw data (CH I/Q) word length
|
alg_opt |
unsigned char |
Reserved |
ch_opt |
unsigned char |
Configure CSI acquisition from leagcy or non-legacy LTF |
csi_role |
unsigned char |
Specify the operational role of devices with Wi-Fi CSI enabled |
mode |
unsigned char |
Specify which mode for fetching Wi-Fi CSI
|
act |
unsigned char |
Enable Wi-Fi CSI or configure Wi-Fi CSI parameters |
trig_frame_mgnt |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_ctrl |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_data |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
enable |
unsigned char |
|
trig_period |
unsigned char |
Wi-Fi CSI sounding rate, unit: 320us (recommended value: 15~255) |
data_rate |
unsigned char |
Specify Tx data rate of CSI triggering frame, but the parameters is invalid in Rx Response Mode for getting Wi-Fi CSI because Wi-Fi CSI dependeds on the data rate of the response ACK frame.
|
data_bw |
unsigned char |
Specify the bandwidth of trigger frame
|
mac_addr[6] |
unsigned char |
Specify destination address (MAC address) for CSI triggering frame (purpose to fetch CSI information from response packet)
|
multi_type |
unsigned char |
Specify whether the CSI triggering frame is unicast or broadcast, only valid in Active CSI.
|
trig_flag |
unsigned char |
Specify role for transmitting CSI triggering frame in METHOD4 and role for transmitting response ACK for CSI triggering frame in METHOD1_Variant, others are reserved.
|
Parameter |
Type |
Description |
---|---|---|
group_num |
unsigned char |
Specify the CSI info subcarrier decimation
|
accuracy |
unsigned char |
Specify the CSI raw data (CH I/Q) word length
|
alg_opt |
unsigned char |
Reserved |
ch_opt |
unsigned char |
Configure CSI acquisition from leagcy or non-legacy LTF |
csi_role |
unsigned char |
Specify the operational role of devices with Wi-Fi CSI enabled |
mode |
unsigned char |
Specify which mode for fetching Wi-Fi CSI
|
act |
unsigned char |
Enable Wi-Fi CSI or configure Wi-Fi CSI parameters |
trig_frame_mgnt |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_ctrl |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_data |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
enable |
unsigned char |
|
trig_period |
unsigned char |
Wi-Fi CSI sounding rate, unit: 320us (recommended value: 15~255) |
data_rate |
unsigned char |
Specify Tx data rate of CSI triggering frame, but the parameters is invalid in Rx Response Mode for getting Wi-Fi CSI because Wi-Fi CSI dependeds on the data rate of the response ACK frame.
|
data_bw |
unsigned char |
Specify the bandwidth of trigger frame, only support 20MHz
|
mac_addr[6] |
unsigned char |
Specify destination address (MAC address) for CSI triggering frame (purpose to fetch CSI information from response packet)
|
multi_type |
unsigned char |
Specify whether the CSI triggering frame is unicast or broadcast, only valid in Active CSI.
|
trig_flag |
unsigned char |
Specify role for transmitting CSI triggering frame in METHOD4 and role for transmitting response ACK for CSI triggering frame in METHOD1_Variant, others are reserved.
|
Parameter |
Type |
Description |
---|---|---|
group_num |
unsigned char |
Specify the CSI info subcarrier decimation
|
accuracy |
unsigned char |
Specify the CSI raw data (CH I/Q) word length
|
alg_opt |
unsigned char |
Reserved |
ch_opt |
unsigned char |
Configure CSI acquisition from leagcy or non-legacy LTF |
csi_role |
unsigned char |
Specify the operational role of devices with Wi-Fi CSI enabled |
mode |
unsigned char |
Specify which mode for fetching Wi-Fi CSI
|
act |
unsigned char |
Enable Wi-Fi CSI or configure Wi-Fi CSI parameters |
trig_frame_mgnt |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_ctrl |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_data |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
enable |
unsigned char |
|
trig_period |
unsigned char |
Wi-Fi CSI sounding rate, unit: 320us (recommended value: 15~255) |
data_rate |
unsigned char |
Specify Tx data rate of CSI triggering frame, but the parameters is invalid in Rx Response Mode for getting Wi-Fi CSI because Wi-Fi CSI dependeds on the data rate of the response ACK frame.
|
data_bw |
unsigned char |
Specify the bandwidth of trigger frame, only support 20MHz
|
mac_addr[6] |
unsigned char |
Specify destination address (MAC address) for CSI triggering frame (purpose to fetch CSI information from response packet)
|
multi_type |
unsigned char |
Specify whether the CSI triggering frame is unicast or broadcast, only valid in Active CSI.
|
trig_flag |
unsigned char |
Specify role for transmitting CSI triggering frame in METHOD4 and role for transmitting response ACK for CSI triggering frame in METHOD1_Variant, others are reserved.
|
Parameter |
Type |
Description |
---|---|---|
group_num |
unsigned char |
Specify the CSI info subcarrier decimation
|
accuracy |
unsigned char |
Specify the CSI raw data (CH I/Q) word length
|
alg_opt |
unsigned char |
Reserved |
ch_opt |
unsigned char |
Configure CSI acquisition from leagcy or non-legacy LTF |
csi_role |
unsigned char |
Specify the operational role of devices with Wi-Fi CSI enabled |
mode |
unsigned char |
Specify which mode for fetching Wi-Fi CSI
|
act |
unsigned char |
Enable Wi-Fi CSI or configure Wi-Fi CSI parameters |
trig_frame_mgnt |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_ctrl |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
trig_frame_data |
unsigned short |
Specify frame type(s) of CSI triggering frame for fetching CSI (used for Rx Normal Mode and no need for Rx Response Mode) |
enable |
unsigned char |
|
trig_period |
unsigned char |
Wi-Fi CSI sounding rate, unit: 320us (recommended value: 15~255) |
data_rate |
unsigned char |
Specify Tx data rate of CSI triggering frame, but the parameters is invalid in Rx Response Mode for getting Wi-Fi CSI because Wi-Fi CSI dependeds on the data rate of the response ACK frame.
|
data_bw |
unsigned char |
Specify the bandwidth of trigger frame, only support 20MHz
|
mac_addr[6] |
unsigned char |
Specify destination address (MAC address) for CSI triggering frame (purpose to fetch CSI information from response packet)
|
multi_type |
unsigned char |
Specify whether the CSI triggering frame is unicast or broadcast, only valid in Active CSI.
|
trig_flag |
unsigned char |
Specify role for transmitting CSI triggering frame in METHOD4 and role for transmitting response ACK for CSI triggering frame in METHOD1_Variant, others are reserved.
|
Parameter Values
The values of
group_num
:/** * @brief csi group num. */ enum { CSI_GROUP_NUM_1 = 0, /**< per tone */ CSI_GROUP_NUM_2, /**< per 2tone */ CSI_GROUP_NUM_4, /**< per 4tone */ CSI_GROUP_NUM_8_16, /**< per 8tone for dplus; per 16tone for others */ CSI_GROUP_NUM_MAX };
The values of
accuracy
:/** * @brief csi accuracy. */ enum { CSI_ACCU_1BYTE = 0, /**< CSI_ACCU_1BYTE: S(8,3) for dplus and S(8,4) for others */ CSI_ACCU_2BYTES, /**< CSI_ACCU_2BYTE: S(16,11) for dplus and S(16,12) for others */ CSI_ACCU_MAX };
The values of
ch_opt
:/** * @brief csi ch_opt. */ enum { CSI_CH_LEGACY = 0, /**< legacy part(L-LTF) channel estmation result */ CSI_CH_NON_LEGACY, /**< non-legacy(HT-LTF) part */ CSI_CH_MAX };
The values of
csi_role
:/** * @brief csi csi_role. */ enum { CSI_OP_ROLE_TRX = 0, /**< both trx */ CSI_OP_ROLE_TX = 1, /**< only tx csi triggering frame */ CSI_OP_ROLE_RX = 2, /**< only rx csi triggering frame for fetching csi report */ CSI_OP_ROLE_MAX };
The values of
mode
:/** * @brief csi mode. */ enum { CSI_MODE_NORMAL = 0, /**< rx normal mode */ CSI_MODE_NDP, /**< rx ndp mode: not support */ CSI_MODE_RX_RESP, /**< rx response mode */ CSI_MODE_MAX, };
The values of
act
:/** * @brief csi enable or config. */ enum { CSI_ACT_EN, /**< enable or disable csi func */ CSI_ACT_CFG, /**< config csi parameters */ CSI_ACT_MAX };
The values of
trig_frame_mgnt
:/** * @brief csi trig management frame subtype. */ enum { CSI_TRIG_ASSOCREQ = BIT(0), CSI_TRIG_ASSOCRSP = BIT(1), CSI_TRIG_REASSOCREQ = BIT(2), CSI_TRIG_REASSOCRSP = BIT(3), CSI_TRIG_PROBEREQ = BIT(4), CSI_TRIG_PROBERSP = BIT(5), CSI_TRIG_BEACON = BIT(8), CSI_TRIG_ATIM = BIT(9), CSI_TRIG_DISASSOC = BIT(10), CSI_TRIG_AUTH = BIT(11), CSI_TRIG_DEAUTH = BIT(12), CSI_TRIG_ACTION = BIT(13) };
The values of
trig_frame_ctrl
:/** * @brief csi trig control frame subtype. */ enum { CSI_TRIG_TRIGGER = BIT(2), CSI_TRIG_BA = BIT(9), CSI_TRIG_PSPOLL = BIT(10), CSI_TRIG_RTS = BIT(11), CSI_TRIG_CTS = BIT(12), CSI_TRIG_ACK = BIT(13), CSI_TRIG_CFEND = BIT(14), CSI_TRIG_CFEND_CFACK = BIT(15) };
The values of
trig_frame_data
:/** * @brief csi trig data frame subtype. */ enum { CSI_TRIG_DATA = BIT(0), CSI_TRIG_DATA_CFACK = BIT(1), CSI_TRIG_DATA_CFPOLL = BIT(2), CSI_TRIG_DATA_CFACKPOLL = BIT(3), CSI_TRIG_DATA_NULL = BIT(4), CSI_TRIG_CF_ACK = BIT(5), CSI_TRIG_CF_POLL = BIT(6), CSI_TRIG_CF_ACKPOLL = BIT(7), CSI_TRIG_QOS_DATA = BIT(8), CSI_TRIG_QOS_DATA_NULL = BIT(12) };
The values of
data_rate
:/** * @brief The enumeration lists the BIT 7 HT Rate. */ enum { MGN_1M = 0x02, /**< 0x02 */ MGN_2M = 0x04, /**< 0x04 */ MGN_5_5M = 0x0B, /**< 0x0B */ MGN_6M = 0x0C, /**< 0x0C */ MGN_9M = 0x12, /**< 0x12 */ MGN_11M = 0x16, /**< 0x16 */ MGN_12M = 0x18, /**< 0x18 */ MGN_18M = 0x24, /**< 0x24 */ MGN_24M = 0x30, /**< 0x30 */ MGN_36M = 0x48, /**< 0x48 */ MGN_48M = 0x60, /**< 0x60 */ MGN_54M = 0x6C, /**< 0x6C */ MGN_MCS0 = 0x80, /**< 0x80 */ MGN_MCS1, /**< 0x81 */ MGN_MCS2, /**< 0x82 */ MGN_MCS3, /**< 0x83 */ MGN_MCS4, /**< 0x84 */ MGN_MCS5, /**< 0x85 */ MGN_MCS6, MGN_MCS7, MGN_UNKNOWN = 0x100 };
/** * @brief The enumeration lists the BIT 7 HT Rate. */ enum { MGN_1M = 0x02, /**< 0x02 */ MGN_2M = 0x04, /**< 0x04 */ MGN_5_5M = 0x0B, /**< 0x0B */ MGN_6M = 0x0C, /**< 0x0C */ MGN_9M = 0x12, /**< 0x12 */ MGN_11M = 0x16, /**< 0x16 */ MGN_12M = 0x18, /**< 0x18 */ MGN_18M = 0x24, /**< 0x24 */ MGN_24M = 0x30, /**< 0x30 */ MGN_36M = 0x48, /**< 0x48 */ MGN_48M = 0x60, /**< 0x60 */ MGN_54M = 0x6C, /**< 0x6C */ MGN_MCS0 = 0x80, /**< 0x80 */ MGN_MCS1, /**< 0x81 */ MGN_MCS2, /**< 0x82 */ MGN_MCS3, /**< 0x83 */ MGN_MCS4, /**< 0x84 */ MGN_MCS5, /**< 0x85 */ MGN_MCS6, MGN_MCS7, MGN_HE1SS_MCS0 = 0xD0, /**< 0xD0 */ MGN_HE1SS_MCS1, MGN_HE1SS_MCS2, MGN_HE1SS_MCS3, MGN_HE1SS_MCS4, MGN_HE1SS_MCS5, MGN_HE1SS_MCS6, MGN_HE1SS_MCS7, MGN_HE1SS_MCS8, MGN_HE1SS_MCS9, MGN_UNKNOWN = 0x100 };
/** * @brief The enumeration lists the BIT 7 HT Rate. */ enum { MGN_1M = 0x02, /**< 0x02 */ MGN_2M = 0x04, /**< 0x04 */ MGN_5_5M = 0x0B, /**< 0x0B */ MGN_6M = 0x0C, /**< 0x0C */ MGN_9M = 0x12, /**< 0x12 */ MGN_11M = 0x16, /**< 0x16 */ MGN_12M = 0x18, /**< 0x18 */ MGN_18M = 0x24, /**< 0x24 */ MGN_24M = 0x30, /**< 0x30 */ MGN_36M = 0x48, /**< 0x48 */ MGN_48M = 0x60, /**< 0x60 */ MGN_54M = 0x6C, /**< 0x6C */ MGN_MCS0 = 0x80, /**< 0x80 */ MGN_MCS1, /**< 0x81 */ MGN_MCS2, /**< 0x82 */ MGN_MCS3, /**< 0x83 */ MGN_MCS4, /**< 0x84 */ MGN_MCS5, /**< 0x85 */ MGN_MCS6, MGN_MCS7, MGN_HE1SS_MCS0 = 0xD0, /**< 0xD0 */ MGN_HE1SS_MCS1, MGN_HE1SS_MCS2, MGN_HE1SS_MCS3, MGN_HE1SS_MCS4, MGN_HE1SS_MCS5, MGN_HE1SS_MCS6, MGN_HE1SS_MCS7, MGN_HE1SS_MCS8, MGN_HE1SS_MCS9, MGN_UNKNOWN = 0x100 };
/** * @brief The enumeration lists the BIT 7 HT Rate. */ enum { MGN_1M = 0x02, /**< 0x02 */ MGN_2M = 0x04, /**< 0x04 */ MGN_5_5M = 0x0B, /**< 0x0B */ MGN_6M = 0x0C, /**< 0x0C */ MGN_9M = 0x12, /**< 0x12 */ MGN_11M = 0x16, /**< 0x16 */ MGN_12M = 0x18, /**< 0x18 */ MGN_18M = 0x24, /**< 0x24 */ MGN_24M = 0x30, /**< 0x30 */ MGN_36M = 0x48, /**< 0x48 */ MGN_48M = 0x60, /**< 0x60 */ MGN_54M = 0x6C, /**< 0x6C */ MGN_MCS0 = 0x80, /**< 0x80 */ MGN_MCS1, /**< 0x81 */ MGN_MCS2, /**< 0x82 */ MGN_MCS3, /**< 0x83 */ MGN_MCS4, /**< 0x84 */ MGN_MCS5, /**< 0x85 */ MGN_MCS6, MGN_MCS7, MGN_VHT1SS_MCS0 = 0xA0, /**< 0xA0 */ MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4, MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9, MGN_HE1SS_MCS0 = 0xD0, /**< 0xD0 */ MGN_HE1SS_MCS1, MGN_HE1SS_MCS2, MGN_HE1SS_MCS3, MGN_HE1SS_MCS4, MGN_HE1SS_MCS5, MGN_HE1SS_MCS6, MGN_HE1SS_MCS7, MGN_HE1SS_MCS8, MGN_HE1SS_MCS9, MGN_UNKNOWN = 0x100 };
wifi_csi_report
Function prototype:
int wifi_csi_report(u32 buf_len, u8 *csi_buf, u32 *len)
Description: fetch Wi-Fi CSI report (CSI header information and CSI raw data)
Parameter Definitions
Parameter |
Type |
Description |
---|---|---|
buf_len |
u32 |
Buffer size for storing CSI packet which specified by APP |
csi_buf |
u8* |
CSI data buffer address for storing CSI packet which specified by APP |
len |
u32* |
Size of CSI raw data |
CSI Buffer Layout
The CSI buffer is divided into two sections: CSI header information and CSI raw data. The size of the raw data is indicated by csi_data_length field within the CSI header information.
CSI buffer layout
CSI Header Information
The CSI header information follows a fixed-order format consisting of predefined fields. The diagram below illustrates the structure of the CSI header information.
CSI header information format
The following list shows the description of each field.
Subfield |
Size (bytes) |
Definition |
---|---|---|
csi_signature |
2 |
Pattern that may be used to detect a new CSI packet. The unique pattern is set to the value 0xABCD. |
hdr_len |
1 |
Length of the CSI header information except the subfields of csi_signature and hdr_len. |
mac_addr |
6 |
Device MAC address, indicates transmitter address of CSI triggering frame in Active CSI and receiver address of CSI triggering frame in Passive CSI. |
trig_addr |
6 |
Device MAC address, indicates destination address of CSI triggering frame in Active CSI and source address of CSI triggering frame in Passive CSI.
|
hw_assigned_timestamp |
4 |
CSI timestamp, unit: us. |
csi_sequence |
4 |
CSI packet sequence number (invalid in METHOD4). |
csi_data_length |
4 |
CSI raw_data length, unit: byte. |
csi_valid |
1 |
Indicate the current CSI raw data whether valid. |
channel |
1 |
Operation channel of current device. |
bandwidth |
1 |
Operation bandwidth.
|
rx_rate |
1 |
Indicate the rate of packet which used to derive CSI. |
protocol_mode |
1 |
Inidcate the protocol mode of the packet which is used to fetch CSI.
|
num_sub_carrier |
2 |
Number of subcarriers contain in CSI raw data. |
num_bit_per_tone |
1 |
CSI data word length (sum of I and Q). Accuracy: S(8,X) or S(16,X) |
rssi[2] |
1 |
Received signal strength, dBm, rssi[1] is reserved. |
evm[2] |
2 |
Error vector magnitude, dB, Reserved. |
rxsc |
1 |
Indicate which sub 20M channel is used to transmit packet. |
n_rx |
1 |
Reserved. |
n_sts |
1 |
Reserved. |
trig_flag |
1 |
Idicates source of role for triggering CSI Valid in only METHOD4 and reserved in other METHODs. |
rsvd |
5 |
Reserved. |
Example of CSI header information & raw data
The following is a comparison of CSI buffer content and parsed CSI header information:
Comparison between the parsed CSI header information and the data in the CSI buffer
CSI Raw Data Layout
A tone index of -20MHz~0 corresponds to 64:127, and 0~20MHz corresponds to 0:63.
legacy 20MHz: tone_index (102, 103, …, 127, 1, 2, …, 26)
non-legacy 20MHz: tone_index (100, 101, 102, 103, …, 127, 1, 2, …, 26, 27, 28)
legacy 40MHz: tone_index (70, 71, …, 94, 95, 97, 98, …, 122, 6, 7, …, 30, 31, 33, 34, …, 57, 58)
non-legacy 40MHz: tone_index (71, 72, …, 127, 1, 2, …, 56, 57)
Example of CSI Raw Data (without Decimation): 20MHz
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a VHT MIMO 1x2 matrix as an example (group_num
: 1 + accuracy
: 0), the sequences of H are H11 and H12.
The layout of CSI raw data is:
CSI raw data layout (without decimation)
Example of CSI Raw Data (with Decimation): 20MHz
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a VHT MIMO 1x2 matrix as an example (group_num
: 3 + accuracy
: 0), the sequences of H are H11 and H12. Select tone idx based on the principle of tone_idx%group_num==0.
The layout of CSI raw data is:
CSI raw data layout (with decimation)
A tone index of 0~20MHz corresponds to 0:63.
Example of CSI Raw Data (without Decimation)
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a HT MIMO 1x2 matrix as an example (group_num
: 1 + accuracy
: 0), the sequences of H are H11 and H12.
The layout of CSI raw data is:
CSI raw data layout (without decimation)
Example of CSI Raw Data (with Decimation)
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a HT MIMO 1x2 matrix as an example (group_num
: 3 + accuracy
: 0), the sequences of H are H11 and H12. The total subcarriers number = ceil((tone_num/2)/group_num) * 2 = ceil(56/2/16)*2 = 4.
The layout of CSI raw data is:
CSI raw data layout (with decimation)
A tone index of 0~20MHz corresponds to 0:63.
Example of CSI Raw Data (without Decimation)
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a HT MIMO 1x2 matrix as an example (group_num
: 1 + accuracy
: 0), the sequences of H are H11 and H12.
The layout of CSI raw data is:
CSI raw data layout (without decimation)
Example of CSI Raw Data (with Decimation)
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a HT MIMO 1x2 matrix as an example (group_num
: 3 + accuracy
: 0), the sequences of H are H11 and H12. The total subcarriers number = ceil((tone_num/2)/group_num) * 2 = ceil(56/2/16)*2 = 4.
The layout of CSI raw data is:
CSI raw data layout (with decimation)
A tone index of 0~20MHz corresponds to 0:63.
Example of CSI Raw Data (without Decimation)
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a HT MIMO 1x2 matrix as an example (group_num
: 1 + accuracy
: 0), the sequences of H are H11 and H12.
The layout of CSI raw data is:
CSI raw data layout (without decimation)
Example of CSI Raw Data (with Decimation)
Each subcarrier (tone) has an Nrx*Nsts CSI matrix. Take a HT MIMO 1x2 matrix as an example (group_num
: 3 + accuracy
: 0), the sequences of H are H11 and H12. The total subcarriers number = ceil((tone_num/2)/group_num) * 2 = ceil(56/2/16)*2 = 4.
The layout of CSI raw data is:
CSI raw data layout (with decimation)
Number of Subcarriers for CSI Raw Data
BW |
1 |
1/2 |
1/4 |
1/8 |
|
---|---|---|---|---|---|
Non-HT |
20M |
52 |
26 |
12 |
6 |
HT |
20M |
56 |
28 |
14 |
6 |
VHT |
20M |
56 |
28 |
14 |
6 |
Non-HT |
40M |
104 |
52 |
24 |
12 |
HT |
40M |
114 |
56 |
28 |
14 |
VHT |
40M |
114 |
56 |
28 |
14 |
1 |
1/2 |
1/4 |
1/16 |
|
---|---|---|---|---|
Non-HT |
52 |
26 |
14 |
4 |
HT |
56 |
28 |
14 |
4 |
HE |
242 |
122 |
62 |
16 |
1 |
1/2 |
1/4 |
1/16 |
|
---|---|---|---|---|
Non-HT |
52 |
26 |
14 |
4 |
HT |
56 |
28 |
14 |
4 |
HE |
242 |
122 |
62 |
16 |
1 |
1/2 |
1/4 |
1/16 |
|
---|---|---|---|---|
Non-HT |
52 |
26 |
14 |
4 |
HT |
56 |
28 |
14 |
4 |
VHT |
56 |
28 |
14 |
4 |
HE |
242 |
122 |
62 |
16 |
wifi_reg_event_handler
Function prototype:
void wifi_reg_event_handler(unsigned int event_cmds, void (*handler_func)(char *buf, int len, int flag, void *user_data), void *handler_user_data)
Description: register a callback function.
- event_cmds:
parameter in, unsigned int event_cmds >> WIFI_EVENT_CSI_DONE
- handler_func:
parameter in, function pointer >> function name
- handler_user_data:
parameter in, void *handler_user_data generally points to user data >> NULL
For example:
/* callback function example */ void example_callback_func(char *buf, int buf_len, int flags, void *userdata) { UNUSED(buf); UNUSED(buf_len); UNUSED(flags); UNUSED(userdata); /* do something */ return; } /* register wifi event callback function */ wifi_reg_event_handler(Element_ID, example_callback_func, NULL);
wifi_unreg_event_handler
Function prototype:
void wifi_unreg_event_handler(unsigned int event_cmds, void (*handler_func)(char *buf, int len, int flag, void *user_data))
Description: release a callback function.
- event_cmds:
parameter in, unsigned int event_cmds >> WIFI_EVENT_CSI_DONE
- handler_func:
parameter in, function pointer >> function name
For example:
/* release wifi event callback function */ wifi_unreg_event_handler(WIFI_EVENT_CSI_DONE, example_callback_func);
Wi-Fi CSI Usage Notes
Basic Requirements
Parameter configurations for different CSI methods should follow example in Collect CSI from Rx ACK Packet in Rx Response Mode, Collect CSI from Rx Broadcast Packet in Rx Normal Mode and Collect CSI from Rx packet in Rx Normal Mode.
Disable power saving mode before enabling Wi-Fi CSI function.
How to disable: Navigate to
component/soc/amebaxxx/usrcfg/ameba_wificfg.c
, locate thewifi_set_user_config()
and modify as follows:wifi_user_config.lps_enable = 0; wifi_user_config.lps_mode = PS_MODE_ACTIVE;
Mandatory parameters: data_rate and must set to be greater than or equal to OFDM rate.
Optional parameters: group_num, accuarcy, ch_opt, csi_role, trig_period, data_bw, trig_frame_xx, trig_flag, multi_type and can be configured as needed.
METHOD4 Design Considerations
METHOD1, METHOD2, METHOD3 and METHOD5 are normal interactions between STA and AP in infrastructure mode, Realtek driver will construct the MAC address of CSI triggering frame in accordance with Wi-Fi protocol standards.
For example, if the Ameba chip acts as the STA role, the frame format specified by the Wi-Fi standards is shown in the following figure:
Interaction between STA and AP in infrastructure mode
However, METHOD4 involves interaction between STAs in infrastructure mode, which is not fully compliant with Wi-Fi protocol standards. To ensure other STAs can receive packets from the target STA, the Ameba chip will forge CSI triggering frame by modifying the MAC address fields of the CSI trigger frames to A1=broadcast address
and A2=BSSID
. This ensures that the MAC layer of Realtek receiving devices does not filter out the packets.
Note
Only when the Realtek MAC layer receives the Wi-Fi packet will it trigger the CSI circuit to capture CSI reports.
Interaction between STA and STA in infrastructure mode
Additionally, METHOD4 has another issue: as shown in the figure above, Ameba2 receives Wi-Fi packets from both Ameba3 and Ameba1 with identical content, making it impossible for Ameba2 to distinguish whether the CSI packet was triggered by Ameba1 or Ameba3. To resolve this issue, we will fill the unique identifier trig_flag
into the Fragment Number subfield in Sequence Control filed of Wi-Fi packet, and this identifier will be carried in the corresponding CSI packet. The application layer can distinguish which device the CSI belongs to base on trig_flag
.
Mapping of trig_flag with STAx
Compiling Wi-Fi CSI Image
Navigate to
{SDK}/amebaxxx_gcc_project
and run the following command:./menuconfig.py
Locate
, select , then save and exit.----Connectivity config---- CONFIG WHC INTF ---> CONFIG WIFI ---> SDK MODE (NORMAL INIC) ---> [ ] Enable WPS [*] Enable CSI [ ] Enable ANTDIV --- CONFIG BT ---> ... --->
Navigate to
{SDK}/amebaxxx_gcc_project
again and run the following command:./build.py -p -a wifi_csi /* compile image with Wi-Fi CSI example */ ./build.py -p /* compile image without Wi-Fi CSI example */
The image bin files (xxx_app.bin & xxx_boot_all.bin) can be found in {SDK}/amebaxxx_gcc_project
after compile done.
Wi-Fi CSI Example
This section describes the framework and implementation details of the Wi-Fi CSI example. The file path is {SDK}\component\example\wifi\wifi_csi
.
Overview of Wi-Fi CSI Example
Wi-Fi CSI Example Implementation Block Diagram
Details of Wi-Fi CSI Example
For guidance on integrating the Ameba SDK and compiling examples, refer to Application Example. The following section details the implementation specifics of the Wi-Fi CSI example.
Example Initialization
The entry function for the Wi-Fi CSI example is defined in app_example()
.
void app_example(void)
{
example_wifi_csi(); /* calling the entry function of wifi CSI example */
}
Wi-Fi CSI Entry Function
After executing Wi-Fi CSI example entry function: example_wifi_csi()
,a CSI processing thread is created.
void example_wifi_csi(void)
{
if (rtos_task_create(NULL, ((const char *)"wifi_csi_thread"), wifi_csi_thread, NULL, 1024 * 4, 0) != SUCCESS) {
RTK_LOGA(NOTAG, "\n\r%s rtos_task_create(wifi_csi_thread) failed", __FUNCTION__);
}
return;
}
Wi-Fi CSI Thread
Waiting for Wi-Fi power-up and connection success.
If the SoftAP role is enabled, Wi-Fi CSI function will only be initiated by the SoftAP, regardless of whether STA role is in an associated state. Once other devices connect to the SoftAP role, the first connected device will be selected to enable the Wi-Fi CSI function.
If no other devices connect to the SoftAP role, execute
rtos_time_delay_ms(2000)
.If the SoftAP role is not enabled, the Wi-Fi CSI function will be enabled after the STA role connects to a realAP.
If STA role is not connected, execute
rtos_time_delay_ms(2000)
.
while (1) { NEXT: if (wifi_is_running(SOFTAP_WLAN_INDEX)) { wifi_get_associated_client_list(&client_info); if (client_info.count) { memcpy(act_param.mac_addr, client_info.mac_list[0].octet, 6); RTK_LOGA(NOTAG, "### SOFTAP Break ###\r\n"); break; } rtos_time_delay_ms(2000); /* 2s */ goto NEXT; } if (wifi_is_running(STA_WLAN_INDEX) && (wifi_get_join_status() == RTW_JOINSTATUS_SUCCESS) && (*(u32 *)LwIP_GetIP(0) != IP_ADDR_INVALID)) { rtos_time_delay_ms(2000); /* 2s */ RTK_LOGA(NOTAG, "### STA Break ###\r\n"); break; } rtos_time_delay_ms(2000); /* 2s */ }
Registering a Wi-Fi CSI callback function
example_wifi_csi_report_cb()
./* register wifi event callback function */ wifi_reg_event_handler(WIFI_EVENT_CSI_DONE, example_wifi_csi_report_cb, NULL);
Initializing a semephore
wc_ready_sema
, and you should use semaphore to signal that a Wi-Fi CSI report is ready./** * should use semaphore to indicate the occurrence of a Wi-Fi event * This example uses the semaphore `wc_ready_sema` to signal that a Wi-Fi CSI report is ready. */ rtos_sema_create(&wc_ready_sema, 0, 0xFFFFFFFF); if (!wc_ready_sema) { RTK_LOGE(NOTAG, "\r\nInit wc_ready_sema failed\r\n\n"); }
Wi-Fi CSI parameters assignment(example configuration for METHOD1/ METHOD2).
/* config csi parameters */ act_param.group_num = CSI_GROUP_NUM_1; act_param.mode = CSI_MODE_RX_RESP; act_param.accuracy = CSI_ACCU_1BYTE; act_param.trig_period = 200; /* units: 320us */ act_param.data_rate = MGN_6M; /* ofdm 6 mpbs*/ act_param.trig_frame_mgnt = 0; /* no need for rx resp mode, default 0*/ act_param.trig_frame_ctrl = 0; /* no need for rx resp mode, default 0*/ act_param.trig_frame_data = 0; /* no need for rx resp mode, default 0*/ act_param.csi_role = CSI_OP_ROLE_TRX;
Configuring Wi-Fi CSI parameters and enabling Wi-Fi CSI.
/* cis cfg and csi en */ act_param.act = CSI_ACT_CFG; /* csi cfg */ wifi_csi_config(&act_param); act_param.act = CSI_ACT_EN; /* csi en */ act_param.enable = 1; wifi_csi_config(&act_param);
Waiting for the semaphore
wc_ready_sema
to be ready and calling APIwifi_csi_report()
to fetch the Wi-Fi CSI packet.while (1) { /* example: when wifi csi rx done, call csi report handle function. */ if (rtos_sema_take(wc_ready_sema, 0xFFFFFFFF) != SUCCESS) { rtos_sema_delete(wc_ready_sema); act_param.act = CSI_ACT_EN; /* csi dis */ act_param.enable = 0; wifi_csi_config(&act_param); break; } csi_buf = rtos_mem_malloc(csi_data_len); if (csi_buf != NULL) { wifi_csi_report(csi_data_len, csi_buf, &len); /*do something for handing csi info: like show csi data */ wifi_csi_show(csi_buf); } else { RTK_LOGE(NOTAG, "\r\n csi_buf malloc fail\r\n"); } if (csi_buf != NULL) { rtos_mem_free(csi_buf); } }
Exit
Disable Wi-Fi CSI function and release the Wi-Fi CSI callback function.
Free the semaphore
wc_ready_sema
.Delete the task.
/* unregister wifi event callback function */ wifi_unreg_event_handler(WIFI_EVENT_CSI_DONE, example_wifi_csi_report_cb); if (wc_ready_sema) { rtos_sema_delete(wc_ready_sema); } rtos_task_delete(NULL);
Wi-Fi CSI Callback Function
When the Wi-Fi driver is ready with a CSI report, it will utilize the Wi-Fi CSI callback function to send a signal to the APP.
For instance, the APP can up the semaphore within the callback function to trigger the execution of wifi_csi_thread()
for fetching a CSI report.
Note
Avoid performing heavy operations in the callback function to prevent impacting reception performance.
The APP can can use the parameter
flags
, which indicates the size of the current Wi-Fi CSI packet.
void example_wifi_csi_report_cb(char *buf, int buf_len, int flags, void *userdata)
{
(void)buf;
(void)buf_len;
(void)userdata;
rtos_sema_give(wc_ready_sema); /* trigger thread */
csi_data_len = flags; /* APP can use for malloc csi_buf */
return;
}