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

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).

../../_images/collecting_csi_from_rx_ack_packet_response_mode.svg

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.

../../_images/collecting_csi_from_rx_broadcast_packet_normal_mode.svg

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).

../../_images/collecting_csi_from_rx_packet_normal_mode.svg

Collect CSI from Rx packet in Rx Normal Mode

Wi-Fi CSI Architecture

Wi-Fi CSI report mainly consists of three modules:

  1. 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.

  2. 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.

  3. 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.

../../_images/csi_architecture.svg

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 parameters

    • act = 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

  • 0: per tone

  • 1: per 2 tone

  • 2: per 4 tone

  • 3: per 8 tone

accuracy

unsigned char

Specify the CSI raw data (CH I/Q) word length

  • 0: S(8,3)

  • 1: S(16,11)

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

  • 0: Rx Normal Mode (estimating CSI by the currently received packet)

  • 2: Rx Response Mode (estimating CSI by receiving ACK for the previous transmission)

  • others reserved

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

  • 0: disable Wi-Fi CSI function

  • 1: enable Wi-Fi CSI function

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.

  • Only support OFDM/HT rate

data_bw

unsigned char

Specify the bandwidth of trigger frame

  • 0: 20MHz

  • 1: 40MHz

  • Others: reserved

mac_addr[6]

unsigned char

Specify destination address (MAC address) for CSI triggering frame (purpose to fetch CSI information from response packet)

  • If multi_type = 1, the mac_addr is reserved.

multi_type

unsigned char

Specify whether the CSI triggering frame is unicast or broadcast, only valid in Active CSI.

  • 0: unicast (using unicast packet and fetching CSI from the ACK for unicast packet)

  • 1: broadcast (using broadcast packet and other devices fetching CSI from the broadcast packet)

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.

  • Value = 1 ~ 15 (0 is 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
    };
    

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.

../../_images/csi_buffer_layout.svg

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.

../../_images/csi_header_information_format.svg

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.

  • Reserved in METHOD4

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.

  • 0: 20MHz

  • 1: 40MHz

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.

  • 0: OFDM

  • 1: HT

  • 2: VHT

  • 3: HE

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:

../../_images/comparison_between_parsed_csi_header_information_data_and_csi_buffer_data.svg

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:

../../_images/csi_raw_data_layout_without_decimation_dplus.svg

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:

../../_images/csi_raw_data_layout_with_decimation_dplus.svg

CSI raw data layout (with decimation)

Number of Subcarriers for CSI Raw Data

{N_tone(BW) * group_num}

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

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 the wifi_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:

../../_images/interaction_between_sta_and_ap_infrastructure_mode.svg

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.

../../_images/interaction_between_sta_and_sta_infrastructure_mode.svg

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.

../../_images/mapping_trig_flag_with_sta.svg

Mapping of trig_flag with STAx

Compiling Wi-Fi CSI Image

  1. Navigate to {SDK}/amebaxxx_gcc_project and run the following command:

    ./menuconfig.py
    
  2. Locate CONFIG WIFI > Enable CSI, select Enable CSI, then save and exit.

    ----Connectivity config----
        CONFIG WHC INTF --->
        CONFIG WIFI --->
                 SDK MODE (NORMAL INIC)  --->
          [ ]    Enable WPS
          [*]    Enable CSI
          [ ]    Enable ANTDIV
          ---
        CONFIG BT --->
        ... --->
    
  3. 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

../../_images/csi_example_flowchart.svg

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

  1. Waiting for Wi-Fi power-up and connection success.

    1. 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).

    2. 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 */
    }
    
  2. 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);
    
  3. 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");
    }
    
  4. 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;
    
  5. 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);
    
  6. Waiting for the semaphore wc_ready_sema to be ready and calling API wifi_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);
       }
    }
    
  7. Exit

    1. Disable Wi-Fi CSI function and release the Wi-Fi CSI callback function.

    2. Free the semaphore wc_ready_sema.

    3. 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;
}