/* * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and * its subsidiaries and affiliates (collectly called MKSEMI). * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into an MKSEMI * integrated circuit in a product or a software update for such product, * must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of MKSEMI nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * 4. This software, with or without modification, must only be used with a * MKSEMI integrated circuit. * * 5. Any software provided in binary form under this license must not be * reverse engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RANGING_LIB_H #define RANGING_LIB_H #include "mk_uwb.h" /** * @addtogroup MK8000_ALGO_Ranging * @{ */ #ifndef CHEST_DUMP_EN #define CHEST_DUMP_EN (1) #endif #ifndef CHEST_DUMP_STS_EN #define CHEST_DUMP_STS_EN (1) #endif // total channel tap number #define MLAGS_LENGTH 160 // output channel tap number #define CE_LEN (128) // Maximum STS segment number #define MAX_STS_SEG_NUM (1) // Maximum STS segment length #define MAX_STS_SEG_LEN (64) // STS buffer number #define STS_BUF_NUM (1) /* for 4 symbol based switching, max size is 2*11*256, buffer size = (11*2*Nsegs*seg_len/4)*4 Byte */ /* for segment based switching, max size is 4*11*256 = 11KB (never switch mode use the same formula to calculate buffer size) */ /* if set 11k, it has memory issue when run time */ /* we may not use segment based switching */ #define STS_BUF_SIZE (11 * MAX_STS_SEG_NUM * MAX_STS_SEG_LEN + 2) struct STS_INF_T { float sts_short_ce[11]; float sts_IQ[22]; float sts_lsp_result[STS_BUF_SIZE]; }; struct RANGING_INF_T { uint32_t CE_CIR[64]; struct MAC_HW_REPORT_T RPT; }; /** Ranging channel status information */ struct RANGING_CSI_T { uint32_t session_id; uint32_t sts_index; uint16_t ranging_status; uint16_t block_index; uint16_t round_index; uint16_t distance_cm; int16_t azimuth; uint8_t ranging_fom; uint8_t azimuth_fom; uint8_t antenna; uint8_t frame_idx; uint8_t reserved[2]; // pre-poll | poll | final | final-data // poll | final // RCM | RIM | RFM | MRM struct FRAME_INF_T { int8_t rssi; int8_t snr; uint8_t rf_gain; uint8_t bb_gain; uint16_t bd_cnt; uint16_t sfd_cnt; int32_t freq_offset; uint32_t channel_power; uint32_t noise_power; int16_t main_tap_power; int16_t first_tap_power; int16_t fap_delta; uint8_t main_tap; uint8_t first_tap; int16_t sts_fap_delta; uint8_t sts_main_tap; uint8_t sts_first_tap; uint16_t error_code; uint8_t nlos; uint8_t fom; int8_t cir[128][2]; float sts_taps[11][2]; } frame[4]; }; typedef struct { uint8_t en_rfg_adj; ///> Enable RF gain adjust logic. Default value: 1 uint8_t en_hpm; ///> Enable high performance mode. Default value: 0 int16_t sfd_offset_db; ///> Offset to be used when SFD metric is used. Default value: 132.0 int16_t agc_offset_db; ///> Offset to be used when AGC gains are used. Default value: 32.0 int16_t snr_offset_init; ///> Initial offset for SNR calculation. Default value: 10.0 } comp_rssi_t; typedef struct { int32_t ce_delta; uint16_t ce_map_loc; uint16_t ce_fap_loc; int32_t sts_delta; uint16_t sts_map_loc; uint16_t sts_fap_loc; uint8_t ce_fom; uint8_t ce_nlos; uint8_t sts_fom; uint8_t sts_nlos; uint32_t ce_map_pwr; uint32_t ce_fap_pwr; uint32_t ce_ch_pwr; uint32_t ce_mean_npwr; uint32_t ce_max_npwr; uint32_t sts_map_pwr; uint32_t sts_fap_pwr; uint32_t sts_ch_pwr; uint32_t sts_mean_npwr; uint32_t sts_max_npwr; uint8_t use_ce_sts; uint8_t sts_valid; uint8_t fap_fom; uint8_t angle_valid; int8_t rssi; int8_t snr; float all_ant_sts_taps[4 * 11]; float per_ant_sts_pwr[4]; float sts_rssi[4]; float sts_fap_iq[8]; float theta_est; float phi_est; float Kfactor; } ranging_result_t; typedef struct { uint8_t local_search_win; ///> Local search window (configured register value). Default: 2 uint8_t en_sts_fap_det; ///> Flag to enable first path detection: 1: Enabled, 0: Disabled uint8_t init_detect_opt; ///> FAP detect option. 0: Original, 1: Enhanced. Default: 1 uint8_t THR_SF1; ///> !!! scale factor 1 for threshold. Default: 8 (Internal test purpose only, not accessible to user) uint8_t THR_SF2; ///> !!! scale factor 2 for threshold. Default: 16 (Internal test purpose only, not accessible to user) uint8_t ant_switching_enabled; ///> 1: Antenna switching is enabled, 0: Antenna switching is not enabled (single antenna mode) uint8_t num_of_antennas; ///> Number of antenna: tied to the mk_phy parameter. Range 1 to 4 uint8_t ant_offset; ///> Antenna offset indicating the main antenna. Tied to the mk_phy parameter. Range 0 to 3 uint8_t en_skip_ant_ports; ///> 0: Disabled (Default), 1: Enabled. When 1, IQ samples from skip_port_idx are not used in computation uint8_t skip_port_idx; ///> 0 to 3. Only used when en_skp_ant_ports = 1. The port index (relative to main port) whose data is not used. Main port is always /// at index 0 uint8_t en_dynamic_port_sel; ///> 0: Disabled (Default), 1: Enabled. When 1, SNR metric for all ports are generated and ports will small SNR (based on /// thres_skip_port) are skipped uint8_t opt_sts_ce; ///> Option for STS CE. 0 (default) - Use sts_short_ce from STS valid module, 1 - Regenerate CE internally using sts store data ///(original method) float total_energy_thres; ///> total energy threshold. Default: 5.0e-5 float par_th; ///> peak to average threshold. default: 6.0 float preecho_thres_lin; ///> Pre-echo threshold linear (take configured register value and generate linear value). Range 0.1 to 0.001. Default 0.01 float ENER_THR1; ///> !!! Energy threshold 1, Usually around 0.05 or 0.06. Default: 0.05 (Internal test purpose only, not accessible to user) float ENER_THR2; ///> !!! Energy threshold 2, Usually around 0.01 or 0.02. Default: 0.01 (Internal test purpose only, not accessible to user) float thres_skip_port; ///> Default: 0.1. When dynamic port selection is enabled then this threshold is used to select good ports } sts_fap_detect_t; typedef struct { uint8_t ch_number; // RF channel number uint8_t tx_sts_config; // STS packet configurator ( Valid values 0 to 3) - only applicable in BPRF and HPRF modes. // Refer to Table 41 of 15.4z standard - specifies where STS is placed uint8_t tx_sts_seg_num; // STS segment number (Valid values 0 to 3). BPRF: 1 segment (parameter value = 0). HPRF: // 1, 2, 3, or 4 segments uint8_t tx_sts_seg_len; // STS segment length (in units of 512 chips). Valid values 0 to 3. BPRF: 64 (parameter // value = 1). HPRF: 0 (32), 1 (64), 2 (128), or 3 (256) uint8_t tx_en_AoD_mode; // 1: Enable AoD mode (assumes that the TX has multiple antennas) uint8_t antenna_array_size; // Number of antenna elements uint8_t xdim_Nrx_ant; // Number of antennas along x-axis uint8_t ant_sw_period; // switching period in symbols uint8_t rx_syms_avail; // Number of symbols (512 chips) available on each dwell uint8_t alg_option; // 1 - classical beamforming, 2 - Capon, 3 - Music uint8_t gen_steering_vec_file; // Generate steering vector file; 0 - Use pre-generated steering vector file, 1 - // Re-generate steering vector file uint8_t en_calib; // Enable calibration option - Only used during steering vector generation uint8_t module_opt; // Module Option - 0: ISA based, 1: Matrix based int8_t tau1; // FE_tp - Default: -12 int8_t tau2; // FE_ti - Default: -10 int8_t tau3; // FE_Fp - Default: -11 (when FE opt = 0) // Default: -8 (When FE opt = 1) int8_t tau4; // FE_Fi - Default: -3 (when FE opt = 0) // Default: -11 (when FE opt = 1) uint8_t fe_opt_Fp; // FE_opt_Fp - 0 or 1 uint8_t cal_mode; // cal_mode uint8_t ant_offset; // antenna offset to indicate the first antenna in STS field uint8_t ant_board_pos; // antenna board position uint8_t sym_cnt_mode; // 0: auto (based on STS parameters), 1: Custom uint8_t aoa_sym_cnt; // Used only when symbol count mode = 1 (i.e. custom). The number of AoA symbols should be less than the total STS symbols uint16_t sts_inlen; sts_fap_detect_t fap_params; } sts_params_t; // Structure holding the angle information for steering vector generation typedef struct { uint8_t Ndim; ///> Number of dimensions. 1 - Azimuth only, 2 - Azimuth and Elevation int16_t az_low; ///> Lower end of azimuth scan range (in degrees) int16_t az_high; ///> Higher end of azimuth scan range (in degrees) uint8_t az_step; ///> Azimuth step size in degrees. Normally 3 int16_t el_low; ///> Lower end of elevation scan range (in degrees) int16_t el_high; ///> Higher end of elevation scan range (in degrees) uint8_t el_step; ///> Elevation step size in degrees. Normally 3 } angle_span_t; // (aux_mode << 4) | (alg_option) enum STS_AUX_OPT_T { // 135us STS_AUX_ANT_IQ_RSSI = ((1 << 4) | 3), // 239us STS_AUX_ANT_IQ_RSSI_PDOA = ((1 << 4) | 0), // 312us STS_AUX_ANT_IQ_RSSI_PDOA_AOA = ((1 << 4) | 2), // 930us STS_AUX_ANT_IQ_RSSI_PDOA_AOA_FOM = ((2 << 4) | 2), }; // Ranging auxiliary information option enum RANGING_AUX_OPT_T { // 10us CE_AUX_CH_PWR_NLOS = 1, // 140us CE_AUX_FOM = 2, // 150us CE_AUX_CH_PWR_NLOS_FOM = 3, }; #ifdef __cplusplus extern "C" { #endif #if CHEST_DUMP_EN #define CIR_LEN 128 #define CE_WIN 16 #define PWR_TH 100 #define TAP_MARGIN 4 extern struct RANGING_CSI_T debug_csi; uint8_t ranging_fom_calculate(struct RANGING_CSI_T *csi, uint8_t frame_start, uint8_t response_fom, uint8_t *response_tap_gaps, uint8_t response_tap_gaps_num); void dump_preamble_cir(uint8_t idx, uint8_t taps_num); void print_preamble_cir(uint32_t seq_num, uint8_t frame_start, uint8_t frame_num); int8_t correct_rssi(int8_t rssi); int8_t correct_snr(int8_t snr); void calculate_first_tap_power(uint8_t frame_start, uint8_t frame_num); int8_t calculate_noise_floor(uint8_t rf_gain, uint8_t bb_gain); uint32_t auto_adjust_filter_coeff(uint8_t idx); #if CHEST_DUMP_STS_EN void dump_sts_cir(uint8_t idx); void print_sts_cir(uint8_t frame_start, uint8_t frame_num); #endif #endif extern int16_t fap_ones_zeros[256] __attribute__((aligned(4))); extern ranging_result_t g_ranging_result; extern sts_params_t g_sts_params; extern struct STS_INF_T *g_sts_cir_buff; extern struct STS_INF_T g_sts_inf[STS_BUF_NUM]; /** * @brief Initialize all the global variables that will be used in the ranging lib. * * @param[in] rframe Ranging frame type, SP0 ~ SP3 * @param [in] opt Options for auxiliary information * 0 (000) - No auxiliary data is generated * 1 (001) - (ch pwr, fap/map pwr, Kfactor, LoS/NLoS) * 2 (002) - (FoM) */ void ranging_lib_init(uint8_t rframe, enum RANGING_AUX_OPT_T opt); /** * @brief Enable or disable ranging debug CSI output * @param[in] en Enable or disable */ void ranging_debug_csi_en_set(uint8_t en); /** * @brief Get ranging debug CSI output status * @return ranging debug CSI output status */ uint8_t ranging_debug_csi_en_get(void); /** * @brief Detect the fisrt path of ranging frame. * @param[in] rssi Rx packet RSSI * @param[in] snr Rx packet SNR * @return delta of the first path */ int32_t ranging_first_path_detect(int8_t rssi, int8_t snr); /** * @brief Calculate timestamp difference. * @param[in] end End timestamp * @param[in] begin Begin timestamp * @return end - begin */ int64_t ranging_timestamp_diff(int64_t end, int64_t begin); /** * @brief Calculate TX timestamp of the ranging frame. * * @param[in] timestamp PHY timer count of TX * @return TX timestamp (unit: 15.65ps) */ int64_t ranging_tx_time(uint32_t timestamp); /** * @brief Calculate RX timestamp of the ranging frame. * * @param[in] ind MAC RX report * @return RX timestamp (unit: 15.65ps) */ int64_t ranging_rx_time(const struct MAC_HW_REPORT_T *ind); /** * @brief Calculate TX timestamp of the ranging frame. * * @param[in] timestamp PHY timer count of TX * @return TX timestamp (unit: 2ns) */ int64_t ranging_tx_time_in_2ns(uint32_t timestamp); /** * @brief Calculate RX timestamp of the ranging frame. * * @param[in] ind MAC RX report * @return RX timestamp (unit: 2ns) */ int64_t ranging_rx_time_in_2ns(const struct MAC_HW_REPORT_T *ind); /** * @brief Get ranging FAP FoM. * * @param[out] NLoS Non-Line of sight flag, 0/1: LoS, 2: Multipath, 3: NLoS * @param[out] FoM FAP confidence measure, 0 ~ 100 */ void ranging_fom_get(uint8_t *NLoS, uint8_t *FoM); /** * @brief Set antenna delay for ranging. * * @param[in] ant_idx antenna port index, from 0 to 3 * @param[in] delay_rstu antenna delay, unit 15.65ps */ void ranging_ant_delays_set(uint8_t ant_idx, int16_t delay_rstu); /** * @brief Get antenna delay for ranging. * * @param[in] ant_idx antenna port index, from 0 to 3 * @return antenna delay of the specified port, unit 15.6ps */ int16_t ranging_ant_delays_get(uint8_t ant_idx); /** * @brief Get UWB RX RSSI. * * @param[out] rssi RSSI (-110 ~ -10) dBm * @param[out] snr SNR (-21 ~ 20) dB */ void ranging_rssi_get(int8_t *rssi, int8_t *snr); /** * @brief Configure STS parameters. * @param[in] rframe Ranging frame type, SP0 ~ SP3 * @param [in] opt STS auxiliary option @ref enum STS_AUX_OPT_T * @param [in] sts_buff_num STS buffer number @ref STS_BUF_NUM * @param [in] sts_buff_len STS buffer length @ref STS_BUF_SIZE * @return Size of samples that need LSP to process */ uint16_t sts_param_config(uint8_t rframe, enum STS_AUX_OPT_T opt, uint8_t sts_buff_num, uint16_t sts_buff_len); /** * @brief Update STS parameters. * @param [in] main_ant RX main antenna */ void sts_param_update(uint8_t main_ant); /** * @brief Enable or disable dynamic port selection * @param [in] enable 0: disable, 1: enable */ void sts_dynamic_port_sel(uint8_t enable); /** * @brief Store LSP result of RX ranging frame. */ void sts_lsp_store(void); /** * @brief Stop storing LSP result of RX ranging frame. */ void sts_lsp_store_stop(void); /** * @brief Validate STS. * @return 1 represents STS is valid */ uint8_t sts_valid_check(void); /** * @brief Detect the fisrt path of ranging frame based on STS. * @param [in] rssi RSSI * @param [in] snr SNR * @return delta of the first path */ int32_t sts_first_path_detect(int8_t rssi, int8_t snr); /** * @brief Calculate RX main antenna based on STS RSSI. * @param [in][out] Input current main antenna ID, ouput updated main antenna ID */ void sts_rx_main_ant_get(uint8_t *id); /** * @brief Get 4 antenna port RSSI. * @return array of 4 antenna port RSSI */ float *sts_4ant_rssi_get(void); /** * @brief Get RSSI result. * * @return RSSI */ float *sts_rssi_output_get(void); /** * @brief Get STS first path IQ of each antenna port, needs to call AoA calculation or PDoA calculation in advanced. * * @return STS first path IQ */ float *sts_first_path_iq_get(void); /** * @brief Function to compute 10*log10 of a number * This function takes in 32-bit integer and outputs 10*log10 in floating point * * @param[in] num Input number * @return the result of 10*log10(num) */ float fast_10log10(uint32_t num); /** * @brief Get ranging library version. * * @return String of ranging library version */ const char *MK8000_get_rangelib_version(void); #ifdef __cplusplus } #endif /** * @} */ #endif // RANGING_LIB_H