| | |
| | | /* |
| | | * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * its subsidiaries and affiliates (collectly called MKSEMI). |
| | | * |
| | | * All rights reserved. |
| | |
| | | #include "mk_aes.h" |
| | | #include "mk_lsp.h" |
| | | #include "mk_power.h" |
| | | #if RANGING_EN |
| | | #include "lib_ranging.h" |
| | | #endif |
| | | |
| | | #include "board.h" |
| | | |
| | | #ifndef RSSI_EN |
| | | #define RSSI_EN 0 |
| | | #define RSSI_EN (0) |
| | | #endif |
| | | |
| | | // single tone power range: -20dBm ~ 10dBm, step: 0.5dB (+/-0.2dB); tx power = -20dBm + 0.5 * power_level (+/- 1.5dB). |
| | |
| | | static const uint8_t (*power_table)[5] = power_table_CH9; |
| | | |
| | | extern int16_t ranging_ant_delays_get(uint8_t ant_idx); |
| | | extern void ranging_ant_delays_set(uint8_t ant_idx, int16_t delay_ps); |
| | | extern int pdoa_ant_delays_get(int16_t *delays, uint8_t rx_ant_num); |
| | | extern int pdoa_ant_delays_set(int16_t *delays, uint8_t rx_ant_num); |
| | | extern int pdoa_ant_space_set(int16_t ant_space); |
| | | extern int pdoa_gain_set(int16_t *gain, uint8_t rx_ant_num); |
| | | extern int pdoa_angle_offset_set(int16_t *angle_offset); |
| | | |
| | | __WEAK int16_t ranging_ant_delays_get(uint8_t ant_idx) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | __WEAK void ranging_ant_delays_set(uint8_t ant_idx, int16_t delay_ps) |
| | | extern void ranging_ant_delays_set(uint8_t ant_idx, int16_t delay_rstu); |
| | | __WEAK void ranging_ant_delays_set(uint8_t ant_idx, int16_t delay_rstu) |
| | | { |
| | | } |
| | | |
| | | extern int pdoa_ant_delays_get(int16_t *delays, uint8_t rx_ant_num); |
| | | __WEAK int pdoa_ant_delays_get(int16_t *delays, uint8_t rx_ant_num) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | extern int pdoa_ant_delays_set(int16_t *delays, uint8_t rx_ant_num); |
| | | __WEAK int pdoa_ant_delays_set(int16_t *delays, uint8_t rx_ant_num) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | extern int pdoa_ant_space_set(int16_t ant_space); |
| | | __WEAK int pdoa_ant_space_set(int16_t ant_space) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | extern int pdoa_gain_set(int16_t *gain, uint8_t rx_ant_num); |
| | | __WEAK int pdoa_gain_set(int16_t *gain, uint8_t rx_ant_num) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | extern int pdoa_angle_offset_set(int16_t *angle_offset); |
| | | __WEAK int pdoa_angle_offset_set(int16_t *angle_offset) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | extern void sts_lsp_store(void); |
| | | __WEAK void sts_lsp_store(void) |
| | | { |
| | | } |
| | | |
| | | int uwb_open(void) |
| | |
| | | mac_init(IRQ_PRIORITY_HIGH, 3, 3, PHY_PAYLOAD_LEN_MAX); |
| | | #endif |
| | | |
| | | #ifdef XIP_EN |
| | | mac_ifs_set(PHY_LIFS_PERIOD_MACCLK_LONG, PHY_SIFS_PERIOD_MACCLK_LONG); |
| | | #endif |
| | | |
| | | #if RSSI_EN |
| | | mac_rssi_calculation_en(1); |
| | | #endif |
| | | |
| | | phy_init(IRQ_PRIORITY_NORMAL); |
| | | phy_init(IRQ_PRIORITY_NONE); |
| | | |
| | | phy_timer_open(1, IRQ_PRIORITY_HIGH); |
| | | |
| | | //LOG_INFO(TRACE_MODULE_DRIVER, "uwb_open\r\n"); |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "uwb_open\r\n"); |
| | | return 0; |
| | | } |
| | | |
| | |
| | | { |
| | | // lna scan dis |
| | | REG_WRITE(0x40000628, (1 << 6) | rx_ant_code[antenna_idx & 0x03]); |
| | | #ifndef RADAR_EN |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "Open ANT%d\r\n", antenna_idx & 0x03); |
| | | #endif |
| | | } |
| | | } |
| | | |
| | |
| | | // low band |
| | | power_table = power_table_CH2; |
| | | } |
| | | } |
| | | |
| | | // 0x0 - Symmetrical Root-Raised-Cosine Pulse |
| | | // 0x1 - Precursor-Free Pulse (FiRa pulse) |
| | | // 0x2 - Precursor-Free Pulse |
| | | void uwb_pulse_shape_set(uint8_t pulse_shape) |
| | | { |
| | | uint32_t value = REG_READ(0x40000404) & ~(0x3U << 16); |
| | | if (pulse_shape == 0) |
| | | { |
| | | REG_WRITE(0x40000404, value | (0x01 << 16)); |
| | | } |
| | | else |
| | | { |
| | | REG_WRITE(0x40000404, value); |
| | | } |
| | | } |
| | | |
| | | // 0x0 - 2ns(500M), 0x3 - 0.92ns(900M), 0x2 - 0.75ns(1.3G) |
| | | void uwb_pulse_width_set(uint8_t width) |
| | | { |
| | | uint32_t val = REG_READ(0x40000404); |
| | | val = val & ~(0x3U << 16); |
| | | val |= (uint32_t)((width & 0x3) << 16); |
| | | REG_WRITE(0x40000404, val); |
| | | } |
| | | |
| | | void uwb_tx_power_set(uint8_t tx_power_level) |
| | |
| | | |
| | | void uwb_calibration_params_set(uint8_t ch_num) |
| | | { |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "Vdd core %u Loopback time %u\r\n", board_param.vdd_core_vol, board_param.loopback_time); |
| | | |
| | | uint8_t ch_idx = CALIB_CH(ch_num); |
| | | for (uint8_t i = 0; i < 4; i++) |
| | | { |
| | | ranging_ant_delays_set(i, board_param.ant_delays[ch_idx][i]); |
| | | ranging_ant_delays_set(i, board_param.ant_delays[ch_idx][i] + board_param.loopback_time); |
| | | } |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "ToF ant delays %d %d %d %d\r\n", board_param.ant_delays[ch_idx][0], board_param.ant_delays[ch_idx][1], |
| | | board_param.ant_delays[ch_idx][2], board_param.ant_delays[ch_idx][3]); |
| | |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "PDoA angle offsets %d %d\r\n", board_param.pdoa_offsets[0], board_param.pdoa_offsets[1]); |
| | | } |
| | | |
| | | void *uwb_configure(uint8_t mode, uint8_t tx_power_level, const struct UWB_CONFIG_T *ppdu_params) |
| | | void uwb_configure(uint8_t mode, uint8_t tx_power_level, struct UWB_CONFIG_T *ppdu_params) |
| | | { |
| | | // RF config |
| | | uwb_channel_switch(ppdu_params->ch_num); |
| | | uwb_rx_antenna_open((enum UWB_RX_ANT_T)ppdu_params->rx_ant_id); |
| | | // Pulse shape |
| | | uwb_pulse_shape_set(ppdu_params->pulse_shape); |
| | | // Antenna |
| | | uwb_rx_antenna_open((enum UWB_RX_ANT_T)ppdu_params->rx_main_ant); |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "Open ANT%d Pulseshape %d\r\n", ppdu_params->rx_main_ant & 0x03, ppdu_params->pulse_shape); |
| | | |
| | | // Generate PHY configuration |
| | | void *sets_a = phy_params_generate(mode, HIGH_PERFORMANCE_MODE_EN, ppdu_params, NULL); |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "PHY params sets %08x\r\n", (uint32_t)sets_a); |
| | | #if 0 |
| | | // Update ppdu_params to generate a new parameter sets |
| | | static uint32_t sets_b[128]; |
| | | phy_params_generate(mode, HIGH_PERFORMANCE_MODE_EN, ppdu_params, sets_b); |
| | | #endif |
| | | // Select a PHY parameter sets to configure |
| | | uwb_params_sets_switch(mode, sets_a); |
| | | // Configure PHY parameters |
| | | phy_params_configure(mode, HIGH_PERFORMANCE_MODE_EN, ppdu_params); |
| | | |
| | | // PHY config |
| | | if (mode & PHY_TX) |
| | | { |
| | | uwb_tx_init(tx_power_level); |
| | | phy_tx_params_set((void *)ppdu_params->phy_params_container); |
| | | } |
| | | |
| | | if (mode & PHY_RX) |
| | | { |
| | | uwb_rx_init(); |
| | | phy_rx_params_set((void *)ppdu_params->phy_params_container); |
| | | } |
| | | |
| | | // MAC config |
| | | mac_crc_mode_configure(ppdu_params->fcs_type); |
| | | |
| | | return sets_a; |
| | | } |
| | | |
| | | void uwb_params_sets_switch(uint8_t mode, void *sets) |
| | | { |
| | | phy_params_sets_enable(sets); |
| | | |
| | | if (mode & PHY_TX) |
| | | { |
| | | phy_tx_regs_config(sets); |
| | | } |
| | | |
| | | if (mode & PHY_RX) |
| | | { |
| | | phy_rx_regs_config(sets); |
| | | } |
| | | } |
| | | |
| | | /* |
| | | scheduled_mode |
| | | 0: Immediately |
| | | 1: Defer to TX |
| | | 2: CSMA-CA TX |
| | |
| | | { |
| | | int ret = 0; |
| | | |
| | | if (scheduled_mode == 2) |
| | | if (scheduled_mode == TX_MODE_CSMACA) |
| | | { |
| | | // Power on radio |
| | | power_on_radio(1, 1); |
| | | ret = mac_tx(EVT_MODE_MAC_FIX_PHY_ASAP, target_time, 0, pkt_data, pkt_len); |
| | | } |
| | | else if (scheduled_mode == 1) |
| | | else if (scheduled_mode == TX_MODE_DEFER) |
| | | { |
| | | power_on_radio(1, 0); |
| | | ret = mac_tx(EVT_MODE_MAC_ASAP_PHY_FIX, target_time, 0, pkt_data, pkt_len); |
| | |
| | | return ret; |
| | | } |
| | | |
| | | int uwb_rx(uint8_t scheduled_mode, uint32_t target_time, uint32_t timeout_us) |
| | | int uwb_rx(uint8_t scheduled_mode, uint32_t target_time, uint32_t timeout) |
| | | { |
| | | int ret = 0; |
| | | |
| | | sts_lsp_store(); |
| | | |
| | | // Power on radio |
| | | power_on_radio(0, 1); |
| | | |
| | | uint32_t lock = int_lock(); |
| | | if (scheduled_mode) |
| | | if (scheduled_mode == RX_MODE_DEFER) |
| | | { |
| | | ret = mac_rx(EVT_MODE_MAC_ASAP_PHY_FIX, target_time, US_TO_PHY_TIMER_COUNT(timeout_us)); |
| | | ret = mac_rx(EVT_MODE_MAC_ASAP_PHY_FIX, target_time, timeout); |
| | | } |
| | | else |
| | | { |
| | | ret = mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, US_TO_PHY_TIMER_COUNT(timeout_us)); |
| | | ret = mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, timeout); |
| | | } |
| | | mac_start(); |
| | | int_unlock(lock); |
| | |
| | | return ret; |
| | | } |
| | | |
| | | /* |
| | | scheduled_mode |
| | | 0: Immediately |
| | | 1: Defer to TX |
| | | */ |
| | | int uwb_loopback(uint8_t *pkt_data, uint16_t pkt_len, uint8_t scheduled_mode, uint32_t target_time) |
| | | { |
| | | int ret = 0; |
| | | |
| | | // Enable loopback function |
| | | mac_loopback_mode_set(1); |
| | | |
| | | #if 0 |
| | | // Disable RX AGC, and use register to configure the gain of LNA and filter; |
| | | uint8_t rf_gain = 3; |
| | | uint8_t bb_gain = 0; |
| | | uint32_t val = (1U << 31) | ((bb_gain & 0x1FU) << 16) | (rf_gain & 0x7U); |
| | | REG_WRITE(0x40000700, val); |
| | | |
| | | val = REG_READ(0x40003040); |
| | | // Disable enAGC |
| | | val &= 0xFFFFFFFE; |
| | | REG_WRITE(0x40003040, val); |
| | | #endif |
| | | |
| | | // Power on radio |
| | | power_on_radio(1, 1); |
| | | |
| | | uint32_t lock = int_lock(); |
| | | |
| | | uint32_t target = REG_READ(0x40000418) + US_TO_PHY_TIMER_COUNT(100); |
| | | // Rx Timeout |
| | | REG_WRITE(0x40000408, target + US_TO_PHY_TIMER_COUNT(500)); |
| | | |
| | | if (scheduled_mode == TX_MODE_DEFER) |
| | | { |
| | | ret = mac_tx(EVT_MODE_MAC_ASAP_PHY_FIX, target_time, 0, pkt_data, pkt_len); |
| | | } |
| | | else |
| | | { |
| | | ret = mac_tx(EVT_MODE_MAC_PHY_ASAP, 0, 0, pkt_data, pkt_len); |
| | | } |
| | | mac_start(); |
| | | |
| | | int_unlock(lock); |
| | | |
| | | // LOG_INFO(TRACE_MODULE_DRIVER, "UWB Loopback %d\r\n", pkt_len); |
| | | return ret; |
| | | } |
| | | |
| | | // cannot work at scheduled mode |
| | | void uwb_rx_force_off(uint8_t int_rpt_dis) |
| | | void uwb_rx_force_off(bool int_rpt_dis) |
| | | { |
| | | while ((REG_READ(0x40000400) & 0x0f) == 6) |
| | | { |
| | | } |
| | | |
| | | uint32_t lock = int_lock(); |
| | | if ((REG_READ(0x40000400) & 0x0f) == 7) |
| | | { |
| | | uint32_t lock = int_lock(); |
| | | uint32_t ts = phy_timer_count_get() + 250; /* 2us timeout */ |
| | | REG_WRITE(0x40000408, ts); /* cfg the rx timeout */ |
| | | if (int_rpt_dis) |
| | | { |
| | | mac_current_rx_report_discard(); |
| | | } |
| | | int_unlock(lock); |
| | | } |
| | | int_unlock(lock); |
| | | } |
| | | |
| | | void uwb_tx_carrier_only(uint8_t on, uint8_t ch_num, uint8_t tx_power_level) |
| | |
| | | |
| | | if (on) |
| | | { |
| | | power_on_radio(1, 0); |
| | | |
| | | // start |
| | | uwb_tx_init(tx_power_level); |
| | | uwb_channel_switch(ch_num); |
| | |
| | | |
| | | // Disable datapath TX clock |
| | | SYSCON->SYS_CMU &= ~(1U << CLOCK_TX); |
| | | |
| | | power_off_radio(); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | // Disable MAC interrupt |
| | | NVIC_DisableIRQ(MAC_IRQn); |
| | | |
| | | uwb_rx(RX_MODE_IMMEDIATE, 0, MS_TO_PHY_TIMER_COUNT(10)); |
| | | delay_us(20); |
| | | |
| | | // MAC_MODE_CONTROL |
| | | REG_WRITE(0x5000A004, 0x00000009); |
| | |
| | | |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "uwb_blocking_tx_start exit\r\n"); |
| | | |
| | | power_off_radio(); |
| | | mac_restart(); |
| | | } |
| | | |
| | |
| | | |
| | | // Disable MAC interrupt |
| | | NVIC_DisableIRQ(MAC_IRQn); |
| | | |
| | | power_on_radio(0, 1); |
| | | |
| | | // MAC_MODE_CONTROL - clear MAC (bug in software mode) |
| | | REG_WRITE(0x5000A004, 0x00000009); |
| | |
| | | |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "uwb_blocking_rx_start exit\r\n"); |
| | | |
| | | power_off_radio(); |
| | | mac_restart(); |
| | | } |
| | | |
| | |
| | | flag_uwb_sw_trx_start = 0; |
| | | LOG_INFO(TRACE_MODULE_DRIVER, "uwb_blocking_trx_stop\r\n"); |
| | | } |
| | | |
| | | #if RANGING_EN |
| | | static volatile uint16_t loopback_num = 300; |
| | | static volatile uint16_t loopback_count = 0; |
| | | |
| | | static volatile uint16_t loopback_rx_timestamp_frac = 0; |
| | | static volatile int16_t loopback_time_min = 32767; |
| | | static volatile int16_t loopback_time_max = -32768; |
| | | static volatile int32_t loopback_time_sum = 0; |
| | | static volatile uint8_t loopback_cal_done = 0; |
| | | |
| | | static void uwb_loopback_tx_process(struct MAC_HW_REPORT_T *tx_report) |
| | | { |
| | | int64_t tx_timestamp = 0; |
| | | uint16_t tx_timestamp_frac = 0; |
| | | // uint32_t tx_timestamp_int = 0; |
| | | int16_t loopback_time = 0; |
| | | |
| | | if ((tx_report->err_code == UWB_TX_OK) && (loopback_rx_timestamp_frac != 0x8000)) |
| | | { |
| | | tx_timestamp = ranging_tx_time(tx_report->timestamp); |
| | | tx_timestamp_frac = tx_timestamp & 0x1ff; |
| | | // tx_timestamp_int = (uint32_t)(tx_timestamp >> 9); |
| | | |
| | | loopback_time = (int16_t)(loopback_rx_timestamp_frac - tx_timestamp_frac); |
| | | |
| | | if (loopback_time > loopback_time_max) |
| | | { |
| | | loopback_time_max = loopback_time; |
| | | } |
| | | else if (loopback_time < loopback_time_min) |
| | | { |
| | | loopback_time_min = loopback_time; |
| | | } |
| | | |
| | | loopback_count++; |
| | | if (loopback_count >= loopback_num) |
| | | { |
| | | // Check later |
| | | loopback_cal_done = 1; |
| | | } |
| | | loopback_time_sum += loopback_time; |
| | | // LOG_INFO(TRACE_MODULE_APP, "Loopback time $%d;\r\n", loopback_time); |
| | | |
| | | // uint32_t val = REG_READ(0x40003050); |
| | | // uint8_t rf_gain = (val & 0x07); |
| | | // uint8_t bb_gain = ((val >> 3) & 0x1f); |
| | | // LOG_INFO(TRACE_MODULE_APP, "rf_gain %u bb_gain %u\r\n", rf_gain, bb_gain); |
| | | } |
| | | } |
| | | |
| | | static void uwb_loopback_rx_process(struct MAC_HW_REPORT_T *rx_report) |
| | | { |
| | | power_off_radio(); |
| | | int64_t rx_timestamp = 0; |
| | | // uint32_t rx_timestamp_int = 0; |
| | | |
| | | if (rx_report->err_code == UWB_RX_OK) |
| | | { |
| | | rx_timestamp = ranging_rx_time(rx_report); |
| | | loopback_rx_timestamp_frac = rx_timestamp & 0x1ff; |
| | | // rx_timestamp_int = (uint32_t)(rx_timestamp >> 9); |
| | | } |
| | | else |
| | | { |
| | | // Loopback error |
| | | loopback_rx_timestamp_frac = 0x8000; |
| | | } |
| | | } |
| | | |
| | | void uwb_loopback_time_update(uint16_t count, struct UWB_CONFIG_T *ppdu_params) |
| | | { |
| | | uint8_t tx_payload[20]; |
| | | uint16_t tx_len = 20; |
| | | |
| | | for (uint8_t i = 0; i < tx_len; i++) |
| | | { |
| | | tx_payload[i] = 0x55; |
| | | } |
| | | |
| | | // high Tx power will cause saturation |
| | | uwb_configure(PHY_TX | PHY_RX, 10, ppdu_params); |
| | | // init ranging lib for timestamp calculation |
| | | ranging_lib_init(ppdu_params->sts_pkt_cfg, CE_AUX_CH_PWR_NLOS_FOM); |
| | | |
| | | mac_callback_t bak_tx_cb; |
| | | mac_callback_t bak_rx_cb; |
| | | |
| | | uint32_t lock = int_lock(); |
| | | mac_get_process_handler(&bak_tx_cb, &bak_rx_cb); |
| | | mac_register_process_handler(uwb_loopback_tx_process, uwb_loopback_rx_process); |
| | | int_unlock(lock); |
| | | |
| | | loopback_num = count; |
| | | loopback_count = 0; |
| | | |
| | | loopback_cal_done = 0; |
| | | loopback_time_sum = 0; |
| | | loopback_time_min = 32767; |
| | | loopback_time_max = -32768; |
| | | |
| | | do |
| | | { |
| | | if (ppdu_params->sts_pkt_cfg == STS_PKT_CFG_3) |
| | | { |
| | | uwb_loopback(NULL, 0, 0, 0); |
| | | } |
| | | else |
| | | { |
| | | uwb_loopback(tx_payload, tx_len, 0, 0); |
| | | } |
| | | |
| | | delay_us(1800); |
| | | |
| | | // Check the MAC busy state |
| | | while (mac_is_busy()) |
| | | { |
| | | } |
| | | |
| | | } while (loopback_cal_done == 0); |
| | | |
| | | board_param.loopback_time = (int16_t)(loopback_time_sum / loopback_num); |
| | | |
| | | LOG_INFO(TRACE_MODULE_APP, "Loopback time [%d, %d] %d \r\n", loopback_time_min, loopback_time_max, board_param.loopback_time); |
| | | |
| | | // Restore MAC callback |
| | | mac_register_process_handler(bak_tx_cb, bak_rx_cb); |
| | | } |
| | | |
| | | void uwb_loopback_calibration(uint8_t wr_nvm_en, uint16_t count, struct UWB_CONFIG_T *ppdu_params) |
| | | { |
| | | uint8_t tx_payload[20]; |
| | | uint16_t tx_len = 20; |
| | | |
| | | for (uint8_t i = 0; i < tx_len; i++) |
| | | { |
| | | tx_payload[i] = 0x55; |
| | | } |
| | | |
| | | // high Tx power will cause saturation |
| | | uwb_configure(PHY_TX | PHY_RX, 10, ppdu_params); |
| | | // init ranging lib for timestamp calculation |
| | | ranging_lib_init(ppdu_params->sts_pkt_cfg, CE_AUX_CH_PWR_NLOS_FOM); |
| | | |
| | | mac_callback_t bak_tx_cb; |
| | | mac_callback_t bak_rx_cb; |
| | | |
| | | uint32_t lock = int_lock(); |
| | | mac_get_process_handler(&bak_tx_cb, &bak_rx_cb); |
| | | mac_register_process_handler(uwb_loopback_tx_process, uwb_loopback_rx_process); |
| | | int_unlock(lock); |
| | | |
| | | uint16_t loopback_time_range[3] = {0xffff, 0xffff, 0xffff}; |
| | | int16_t loopback_time_avg[3]; |
| | | loopback_num = count; |
| | | |
| | | for (uint8_t j = 0; j < 3; j++) |
| | | { |
| | | // VDD_core voltage ranging [1, 2, 3] |
| | | board_param.vdd_core_vol = j + 1; |
| | | loopback_cal_done = 0; |
| | | loopback_count = 0; |
| | | loopback_time_sum = 0; |
| | | loopback_time_min = 32767; |
| | | loopback_time_max = -32768; |
| | | |
| | | do |
| | | { |
| | | if (ppdu_params->sts_pkt_cfg == STS_PKT_CFG_3) |
| | | { |
| | | uwb_loopback(NULL, 0, 0, 0); |
| | | } |
| | | else |
| | | { |
| | | uwb_loopback(tx_payload, tx_len, 0, 0); |
| | | } |
| | | |
| | | delay_us(1800); |
| | | |
| | | // Check the MAC busy state |
| | | while (mac_is_busy()) |
| | | { |
| | | } |
| | | |
| | | } while (loopback_cal_done == 0); |
| | | |
| | | loopback_time_range[j] = (uint16_t)(loopback_time_max - loopback_time_min); |
| | | loopback_time_avg[j] = (int16_t)(loopback_time_sum / loopback_num); |
| | | #if 0 |
| | | // Set a condition to speed up calibration |
| | | if (loopback_time_range[j] < 30) |
| | | { |
| | | break; |
| | | } |
| | | #endif |
| | | } |
| | | |
| | | uint8_t idx = 0; |
| | | if (loopback_time_range[2] > loopback_time_range[1]) |
| | | { |
| | | if (loopback_time_range[0] > loopback_time_range[1]) |
| | | { |
| | | // 2 > 0 > 1 |
| | | idx = 1; |
| | | } |
| | | else |
| | | { |
| | | // 2 > 1 >= 0 |
| | | idx = 0; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (loopback_time_range[2] > loopback_time_range[0]) |
| | | { |
| | | // 1 >= 2 > 0 |
| | | idx = 0; |
| | | } |
| | | else |
| | | { |
| | | // 1 >= 0 >= 2 |
| | | idx = 2; |
| | | } |
| | | } |
| | | board_param.vdd_core_vol = idx + 1; |
| | | board_param.loopback_time = loopback_time_avg[idx]; |
| | | |
| | | LOG_INFO(TRACE_MODULE_APP, "Loopback %u %u %u [%d]%d\r\n", loopback_time_range[0], loopback_time_range[1], loopback_time_range[2], board_param.vdd_core_vol, |
| | | board_param.loopback_time); |
| | | |
| | | // Restore MAC callback |
| | | mac_register_process_handler(bak_tx_cb, bak_rx_cb); |
| | | // Write NVM |
| | | if (wr_nvm_en) |
| | | { |
| | | board_calibration_param_write(BOARD_VDD_CORE_VOL, &board_param.vdd_core_vol, sizeof(board_param.vdd_core_vol)); |
| | | board_calibration_param_write(BOARD_LOOPBACK_TIME, (uint8_t *)&board_param.loopback_time, sizeof(board_param.loopback_time)); |
| | | } |
| | | } |
| | | #else |
| | | void uwb_loopback_calibration(uint8_t wr_nvm_en, uint16_t count, struct UWB_CONFIG_T *ppdu_params) |
| | | { |
| | | UNUSED(wr_nvm_en); |
| | | UNUSED(count); |
| | | UNUSED(ppdu_params); |
| | | } |
| | | #endif |