/* * Copyright (c) 2019-2023 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 MK_PHY_H_ #define MK_PHY_H_ #include "mk_common.h" /** * @addtogroup MK8000_PHY * @{ */ /** PHY supported maximum payload length */ #ifndef PHY_PAYLOAD_LEN_MAX #define PHY_PAYLOAD_LEN_MAX 1023 #endif /** us to PHY timer count converter, x <= 3,441,480 us */ #define US_TO_PHY_TIMER_COUNT(x) ((x)*1248U / 10U) /** ms to PHY timer count converter x <= 34,414 ms */ #define MS_TO_PHY_TIMER_COUNT(x) ((x)*124800U) /** PHY timer count to us converter, resolution 10us */ #define PHY_TIMER_COUNT_TO_US(x) (((x) / 1248U) * 10U) /** PHY timer count to us converter, allow long long type multiply operation to promote precision */ #define PHY_TIMER_COUNT_TO_US_LL(x) (uint32_t)(((uint64_t)(x)*10U / 1248U)) /** PHY timer count to ms converter */ #define PHY_TIMER_COUNT_TO_MS(x) ((x) / 124800U) /** PHY timer count to MAC timer count converter */ #define PHY_TIMER_COUNT_TO_MAC_TIMER_COUNT(x) ((x) >> 1) /** RSTU to PHY timer count converter, x <= 41,297,762 RSTU */ #define RSTU_TO_PHY_TIMER_COUNT(x) ((x)*104U) /** RSTU to us converter, x <= 429,496,729 RSTU */ #define RSTU_TO_US(x) ((x)*10U / 12U) /** RSTU to ms converter */ #define RSTU_TO_MS(x) ((x) / 1200U) /** Timestamp unit is 15.65ps */ #define TIMESTAMP_UNIT_TO_NS(x) ((x) * (1000 / 499.2 / 128)) /// MeanPRF 62.4M, Data rate 6.8M, x=preamble length, y=SFD length, z=payload length #define PHY_SP0_FRAME_TIME_US(x, y, z) ((((x) + (y)) * 508 + 21 * 512 + ((((z)*8) / 330) * (378) + (((z)*8) % 330) + 48) * 64) / 499 + 1) /// MeanPRF 62.4M, Data rate 6.8M, x=preamble length, y=SFD length, z=payload length, s=STS length #define PHY_FRAME_TIME_US(x, y, z, s) ((((x) + (y)) * 508 + 21 * 512 + ((((z)*8) / 330) * (378) + (((z)*8) % 330) + 48) * 64 + (s)*512 + 1024) / 499 + 1) /** sleep count to PHY timer count converter */ #define SLEEP_COUNT_TO_PHY_TIMER_COUNT(x) ((uint32_t)((float)(x) * (124800000.0f / 32768.0f))) /** The maximum sleep time of PHY, 10s */ #define PHY_SLEEP_TIME_MS_MAX (10000U) /** The minimum sleep time of PHY, 2000us */ #define PHY_SLEEP_TIME_US_MIN (2000U) /// Low power mode clock drift compensation for phy timer count, p = ppm, t = interval(ms) #define LPM_PPM_COMPENSATION(p, t) ((p)*2 * (t)*1248 / 10000) #define TX_PAYLOAD_ADDR 0x02080000 #define RX_PAYLOAD_ADDR 0x02081000 /// Data bit rate, range 0 to 4. 0 - 0.11, 1 - 0.85, 2 - 1.70, 3 - 6.81, 4 - 27.24 Mbps, 5 - 54.48 Mbps #define DATA_BR_110K 0 #define DATA_BR_850K 1 #define DATA_BR_1M7 2 #define DATA_BR_6M8 3 #define DATA_BR_27M2 4 #define DATA_BR_54M4 5 /// PHR bit rate #define PHR_BR_110K 0 #define PHR_BR_850K 1 /// PHR bit rate in BPRF and HPRF mode #define BPRF_PHR_BR_850K 0 #define BPRF_PHR_BR_6M8 1 /// mean prf. 0 - 4, 1 - 16, 2 - 64, 3 - 128, 4 - 256 #define MEAN_PRF_4M 0 #define MEAN_PRF_16M 1 #define MEAN_PRF_64M 2 #define MEAN_PRF_128M 3 #define MEAN_PRF_256M 4 /// Preamble duration, length of preamble sync: 0 - 16, 1 - 64, 2 - 128, 3 - 256, 4 - 512, 5 - 1024, 6 - 2048, 7 - 4096 #define PREAM_LEN_16 0 #define PREAM_LEN_64 1 #define PREAM_LEN_128 2 #define PREAM_LEN_256 3 #define PREAM_LEN_512 4 #define PREAM_LEN_1024 5 #define PREAM_LEN_2048 6 #define PREAM_LEN_4096 7 /// HRPF mode: 0 - 16, 1 - 24, 2 - 32, 3 - 48, 4 - 64, 5 - 96, 6 - 128, 7 - 256 #define HPRF_PREAM_LEN_16 0 #define HPRF_PREAM_LEN_24 1 #define HPRF_PREAM_LEN_32 2 #define HPRF_PREAM_LEN_48 3 #define HPRF_PREAM_LEN_64 4 #define HPRF_PREAM_LEN_96 5 #define HPRF_PREAM_LEN_128 6 #define HPRF_PREAM_LEN_256 7 /// Length of preamble SFD: 0 - 8, 1 - 64 #define NSFD_8 0 #define NSFD_64 1 /// BPRF SFD: 0 - 8 SFD, 2 - 8 SFD2 #define BPRF_NSFD_8 0 #define BPRF_NSFD2_8 2 /// HPRF SFD: 0 - 8 SFD, 1 - 4 SFD1, 2 - 8 SFD2, 3 - 16 SFD3, 4 - 32 SFD4 #define HPRF_NSFD0_8 0 #define HPRF_NSFD1_4 1 #define HPRF_NSFD2_8 2 #define HPRF_NSFD3_16 3 #define HPRF_NSFD4_32 4 /// Non-standard SFD #define NON_STD_NSFD5_8 5 #define NON_STD_NSFD6_16 6 #define HPRF_PSDU_SIZE_1023 0 #define HPRF_PSDU_SIZE_2047 1 #define HPRF_PSDU_SIZE_4095 2 /// 0 - 15.4a(2015), 1 - BPRF, 2 - HPRF, 3 - Proprietary #define TRX_MODE_15_4A 0 #define TRX_MODE_15_4Z_BPRF 1 #define TRX_MODE_15_4Z_HPRF 2 #define TRX_MODE_PROPRIETARY 3 /// SYNC-SFD-PHR-PSDU #define STS_PKT_CFG_0 0 /// SYNC-SFD-STS-PHR-PSDU #define STS_PKT_CFG_1 1 /// SYNC-SFD-PHR-PSDU-STS #define STS_PKT_CFG_2 2 /// SYNC-SFD-STS #define STS_PKT_CFG_3 3 /// STS_SEGNUM /// BPRF: 0 - 1 /// HPRF: 0 - 1, 1 - 2, 2 - 3 (optional), 3 - 4 (optional) #define STS_SEGNUM_BPRF_1 0 #define STS_SEGNUM_HPRF_1 0 #define STS_SEGNUM_HPRF_2 1 #define STS_SEGNUM_HPRF_3 2 #define STS_SEGNUM_HPRF_4 3 /// STS_SEGLEN /// BPRF: 2 - 64 /// HPRF: 0 - 16 (optional), 1 - 32, 2 - 64, 3 - 128, 4 - 256 (optional) #define STS_SEGLEN_BPRF_64 2 #define STS_SEGLEN_HPRF_16 0 #define STS_SEGLEN_HPRF_32 1 #define STS_SEGLEN_HPRF_64 2 #define STS_SEGLEN_HPRF_128 3 #define STS_SEGLEN_HPRF_256 4 /** PHY work mode */ enum PHY_WORK_MODE_T { PHY_IDLE = 0, PHY_TX = 1, PHY_RX = 2, }; /** PHY protocol data unit parameters */ struct UWB_CONFIG_T { uint8_t ch_num; uint8_t code_index; uint8_t mean_prf; uint8_t data_bit_rate; uint8_t sync_sym; uint8_t sfd_sym; uint8_t ranging_bit; uint8_t trx_mode; uint8_t sts_pkt_cfg; uint8_t sts_segnum; uint8_t sts_seglen; uint8_t rx_ant_id; uint8_t fcs_type; }; /** STS key configuration*/ struct UWB_STS_KEY_CONFIG_T { uint32_t sts_vcounter; uint32_t sts_vupper0; uint32_t sts_vupper1; uint32_t sts_vupper2; uint32_t sts_key0; uint32_t sts_key1; uint32_t sts_key2; uint32_t sts_key3; }; /** PHY advanced configuration*/ struct PHY_ADV_CONFIG_T { // 20-200, default:40 uint16_t thres_fap_detect; // 0-15, default:4 uint8_t nth_scale_factor; // 0: high STDEV mode (default), 1: high 1st path dynamic range mode (20db+), 2: STS based FAP, 3: preamble FAP and STS FAP combination uint8_t ranging_performance_mode; // 0: disable, 1: enable uint8_t skip_weakest_port_en; }; /** PHY user configuration*/ struct PHY_USER_CONFIG_T { // AGC uint8_t highTH; uint8_t lowTH; uint8_t nCHUP; uint8_t nLEAK; // Preamble uint8_t symPerBlk[2]; uint8_t pdbLen; uint8_t passNum; uint8_t bdAbsThr[4]; uint8_t deltaPos; uint8_t testSf[2]; uint8_t prmKp; uint8_t prmKi; uint8_t prmKp_time; uint8_t prmKi_time; // CE uint8_t ceStartSym; uint8_t ceAvgIdx; uint8_t ceTapSidx; uint8_t nthr; uint8_t firTapThr[2]; uint8_t srchWinLenM1; // SFD uint8_t engthr0[2]; uint8_t engthr1[2]; // PLD uint8_t pldKp; uint8_t pldKi; uint8_t pldKp_time; uint8_t pldKi_time; // ALGO uint8_t frac_comp_opt[2]; uint8_t lut_step_size[2]; uint8_t win_adj_sf[2]; uint8_t en_simple_frac[2]; uint8_t Coeff0[4]; }; /** STS receive mode */ enum STS_SWITCH_MODE_T { STS_SWITCH_EVERY_4SYM = 0, STS_NEVER_SWITCH = 2, }; #ifdef __cplusplus extern "C" { #endif extern const float ch_center_freq_map[16]; extern const uint8_t rx_ant_code[4]; extern struct PHY_USER_CONFIG_T phy_user_params; /** * @brief Initialize PHY. * @param[in] priority PHY interrupt priority @ref IRQ_PRIORITY_LEVEL_T * @return 0 represent intialization successful */ int phy_init(enum IRQ_PRIORITY_LEVEL_T priority); /** * @brief Register PHY interrupt callback function. * @param[in] callback Callback function of PHY interrupt */ void phy_register_callback(drv_callback_t callback); /** * @brief set TRX mode. * @param[in] mode TRX mode: 0 - 15.4a(2015), 1 - BPRF, 2 - HPRF, 3 - Proprietary * @note: In most of case, change TRX mode needs to reconfigure PHY parameters */ void phy_trx_mode_set(uint8_t mode); /** * @brief Enable PHY parameter sets. * @param[in] sets PHY parameter sets to be enabled, if input NULL the default parameter sets will be used */ void phy_params_sets_enable(void *sets); /** * @brief Generate PHY parameters Configuration. * @param[in] mode Work mode, PHY_TX or PHY_RX or both * @param[in] high_pfm_en Enable or disable high performance mode * @param[in] config PHY protocol data unit parameters @ref UWB_CONFIG_T * @param[in] sets Specify a buffer to store the parameter sets, if input NULL the default parameter sets buffer will be used, * the buffer size is 128 Words, i.e. uint32_t sets[128] * @return the pointer of input parameter sets, if input parameter sets is NULL, the default parameter sets pointer will be returned */ void *phy_params_generate(uint8_t mode, uint8_t high_pfm_en, const struct UWB_CONFIG_T *config, void *sets); /** * @brief Configure PHY adv parameters. * @param[in] config PHY advanced configuration parameters @ref PHY_ADV_CONFIG_T * @return 0 represent configure successfully */ int phy_adv_params_configure(struct PHY_ADV_CONFIG_T *adv_config); /** * @brief Configure PHY parameters for user scenarios. * @param[in] config PHY user configuration parameters @ref PHY_USER_CONFIG_T * @param[in] len PHY user configuration parameters length * @param[in] enable Enable PHY user parameters * @return 0 represent configure successfully */ int phy_loop_params_configure(const struct PHY_USER_CONFIG_T *user_config, uint8_t len, uint8_t enable); /** * @brief Configure PHY transmitter registers. * @param[in] sets PHY parameter sets to be set, if input NULL the default parameter sets will be set * @return 0 represent configure successfully */ int phy_tx_regs_config(void *sets); /** * @brief Configure PHY receiver registers. * @param[in] sets PHY parameter sets to be set, if input NULL the default parameter sets will be set * @return 0 represent configure successfully */ int phy_rx_regs_config(void *sets); /** * @brief Set ranging bit in PHY header. */ void phy_ranging_bit_set(uint8_t bit); /** * @brief Configure UWB TX packet payload * @param[in] data Pointer of the TX packet buffer * @param[in] len TX packet length */ void phy_tx_payload(const uint8_t *data, uint16_t len); /** * @brief the length of synchronization header depends on preamble and SFD symbols, i.e. from the start point of TX_EN/RX_EN to Rframe marker. * @return the time of synchronization header(SHR), unit: 1/124.8M (~8ns) */ uint32_t phy_shr_duration(void); /** * @brief Restore PHY from power-down. * @param[in] sets PHY parameter sets to be restored, if input NULL the default parameter sets will be restored */ void phy_restore(void *sets); /** * @brief Set receiver antenna mode. * @param[in] mode Receiver antenna mode @ref macro definition RX_xPORTS_ANT_xxx */ void phy_rx_ant_mode_set(uint8_t mode); /** * @brief Set AoA symbol count. * @param[in] cnt AoA symbol count, 0x30 or 0x40 */ void phy_aoa_sym_cnt_set(uint16_t cnt); /** * @brief Set STS packet configuration. * @param[in] cfg STS packet configuration, 0 ~ 3 */ void phy_sts_pkt_cfg_set(uint8_t cfg); /** * @brief Set STS key configuration. * @param[in] sts STS key configuration @ref UWB_STS_KEY_CONFIG_T */ void phy_sts_key_configure(struct UWB_STS_KEY_CONFIG_T *sts); /** * @brief Set STS RX antenna switching mode (AoA). * @param[in] sts_pkt_cfg STS packet configuration, SP1 or SP3 * @param[in] mode STS RX antenna switching mode @ref enum STS_SWITCH_MODE_T, this API should be called after configure UWB parameters * @param[in] main_ant_update Update main antenna or not * @param[in] rx_ant_id RX antenna ID */ void phy_rx_sts_switch_mode_set(uint8_t sts_pkt_cfg, enum STS_SWITCH_MODE_T mode, uint8_t main_ant_update, uint8_t rx_ant_id); /** * @brief Set STS TX antenna switching mode (AoD). * @param[in] tx_ant_num Then number of TX antennas to be used for switching, from 1 to 16 * @param[in] mode STS TX antenna switching mode @ref enum STS_SWITCH_MODE_T */ void phy_tx_sts_switch_mode_set(uint8_t tx_ant_num, enum STS_SWITCH_MODE_T mode); /** * @brief Open the PHY timer (124.8MHz free running counter). * @param[in] int_en Enable interrupt flag * @param[in] priority PHY timer interrupt priority @ref IRQ_PRIORITY_LEVEL_T * @return 0 reresent PHY timer is opened */ int phy_timer_open(uint8_t int_en, enum IRQ_PRIORITY_LEVEL_T priority); /** * @brief Close the PHY timer. * @return 0 reresent PHY timer is closed */ int phy_timer_close(void); /** * @brief Set a target time for the PHY timer. * @param[in] target Target time (124.8MHz clock). * @param[in] callback Callback function for the target time */ void phy_timer_target_set(uint32_t target, drv_callback_t callback); /** * @brief Get the flag that PHY timer is set or not. * @return 0 means PHY timer is not set. */ uint8_t phy_timer_is_programmed(void); /** * @brief Get the PHY timer count. * @return PHY timer count (124.8MHz clock). */ uint32_t phy_timer_count_get(void); /** * @brief Get the PHY timer left count. * @return PHY timer left count (124.8MHz clock). */ uint32_t phy_timer_count_left(void); /** * @brief Pause the PHY timer. */ void phy_timer_pause(void); /** * @brief Resume the PHY timer. * @return sleep count @32KHz. */ uint32_t phy_timer_resume(void); /** * @brief Get Burst Detection count * @return Burst Detection count. */ uint16_t phy_bd_cnt_get(void); /** * @brief Get SFD detection count * @return SFD detection count. */ uint16_t phy_sfd_cnt_get(void); /** * @brief Get the UWB Receiver frequency offset compared to the transmitter * @return frequency offset (Hz). */ int32_t phy_freq_offset_get(void); /** * @brief Configure narrow band filter. * @param[in] en Enable or disable * @param[in] in_band_freq_offset In band frequency offset -249.6 ~ 249.6 MHz * @param[in] band_width Narrow band filter band width * 6 - 1.24M * 5 - 2.48M * 4 - 4.96M * 3 - 9.92M * 2 - 19.84M * @return 0 represent configure successfully */ int phy_nb_filter_config(uint8_t en, int16_t in_band_freq_offset, uint8_t band_width); /** * @brief Get narrow band energy. * @return narrow band energy */ int32_t phy_nb_energy_get(void); /** * @brief Configure CCA. */ void phy_cca_config(void); /** * @brief Start CCA. * @param[in] int_en 1 - Interrupt mode, 0 - Polling mode * @param[in] callback Callback function of PHY interrupt * @return RSSI in polling mode, for interrupt mode, the result should be read in callback function */ uint16_t phy_cca_start(uint8_t int_en, drv_callback_t callback); /** * @brief Get CCA RSSI. * @return CCA RSSI */ int32_t phy_cca_rssi_get(void); /** * @brief Enable dump mode. * @param[in] en 1 - Enable, 0 - Disable */ void phy_dump_en(uint8_t en); /** * @brief Enter debug mode. */ void enter_debug_mode(void); #ifdef __cplusplus } #endif /** * @} */ #endif /* MK_PHY_H_ */