/* * 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. */ #include "mk_uwb.h" #include "mk_radar.h" #include "mk_trace.h" #include "mk_misc.h" #include "mk_lsp.h" #ifndef UWB_RADAR_1TNR_MODE /* 1TnR radar mdoe: 0: Single, 1: Overlay */ #define UWB_RADAR_1TNR_MODE 0 #endif #ifndef UWB_RADAR_RX_PORT_NUM /* 1TnR mode RX port number */ #define UWB_RADAR_RX_PORT_NUM 1 #endif #ifndef UWB_RADAR_STS_LENGTH #define UWB_RADAR_STS_LENGTH 2 #endif /* Overlay Length of Frames */ #define OVERLAY_FRAME_LENGTH 128 /* Cut off unwantted data at both ends */ #define CUT_OFF_LINES(n) ((n * 1024) / (OVERLAY_FRAME_LENGTH * 2)) /* Ignore n KB data at head */ #define HEAD_LEN (2) /* Ignore n KB data at tail */ #define TAIL_LEN (2) /* Snapshot size, x = STS segment length: 0, 1, 2 */ #define ACCUMULATE_ROWS(x) (DUMP_DATA_SIZE(x) / (OVERLAY_FRAME_LENGTH * 2)) #if UWB_RADAR_1TNR_MODE == 0 /* Accumulation times, depends on STS length and Frame length */ #define N_SNAPSHOTS (ACCUMULATE_ROWS(UWB_RADAR_STS_LENGTH)) #else /* Accumulation times, depends on STS length, Frame length and RX port number */ #define N_SNAPSHOTS (ACCUMULATE_ROWS(UWB_RADAR_STS_LENGTH) / (1 << (UWB_RADAR_RX_PORT_NUM - 1))) #endif #if OVERLAY_FRAME_LENGTH == 256 #if (64 == N_SNAPSHOTS) #elif (128 == N_SNAPSHOTS) #elif (256 == N_SNAPSHOTS) #else #error "N_SNAPSHOTS is not supported" #endif #elif OVERLAY_FRAME_LENGTH == 128 #if (128 == N_SNAPSHOTS) #elif (256 == N_SNAPSHOTS) #elif (512 == N_SNAPSHOTS) #else #error "N_SNAPSHOTS is not supported" #endif #else #error "Frame length is not supported" #endif /* Radar RX window, unit: us */ #define UWB_RADAR_RX_WINDOW (100) /* Radar event prefetch time, unit: us */ #define UWB_RADAR_PREFETCH_TIME (100) #if UWB_RADAR_1TNR_MODE == 1 #if UWB_RADAR_STS_LENGTH == 2 #define UWB_RADAR_RX_WINDOW2 64 #define UWB_RADAR_RX_WINDOW3 48 #else #define UWB_RADAR_RX_WINDOW2 48 #define UWB_RADAR_RX_WINDOW3 40 #endif #endif /* 1TnR Frame interval for Overlay work mode, unit: us */ #define FRAME_INTERVAL 300 /* The factors influencing the peak index value are twofold: * 1) the scheduled transmission time (The configuration of the low 2 bits of the 0x40000424 register) * 2) the value of the discard (0x40002040 bit8~19) */ /* The low 2 bits of the 0x40000424 register are set to 0 * |----------------------------------------------------------------------------| * | Discard Symbols(24/25/26/27/28/29) | 24 | 25 | 26 | 27 | 28 | 29 | | * |----------------------------------------------------------------------------| * | Pulse period 16ns (0 Delay Point) | 4 | 12 | 4 | 12 | 4 | 12 | | * |----------------------------------------------------------------------------| * |----------------------------------------------------------------------------| * | Pulse period 32ns (0 Delay Point) | 20 | 28 | 4 | 12 | 20 | 28 | | * |----------------------------------------------------------------------------| * |----------------------------------------------------------------------------| * | Pulse period 64ns (0 Delay Point) | 36 | 44 | 52 | 60 | 4 | 12 | | * |----------------------------------------------------------------------------| * |----------------------------------------------------------------------------| * | Pulse period 128ns (0 Delay Point) | 100 | 108 | 116 | 124 | 4 | 12 | | * |----------------------------------------------------------------------------| * |----------------------------------------------------------------------------| * | Pulse period 256ns (0 Delay Point) | 228 | 236 | 244 | 252 | 4 | 12 | | * |----------------------------------------------------------------------------| */ #if UWB_RADAR_2G_MODE_EN /* 1ns per sample, 24 ~ 27 */ #define DISCARD_SYMBOLS 25 /* pusle peak postion table */ static const uint8_t peak_idx_table[5][4] = {{4, 12, 4, 12}, {20, 28, 4, 12}, {36, 44, 52, 60}, {100, 108, 116, 124}, {228, 236, 244, 252}}; #else /* 2ns per sample, 12 ~ 15 */ #define DISCARD_SYMBOLS 12 /* pusle peak postion table */ static const uint8_t peak_idx_table[5][4] = {{1, 5, 1, 5}, {0, 4, 8, 12}, {8, 12, 16, 20}, {8, 12, 16, 20}, {72, 76, 80, 84}}; #endif /* 1TnR Rx port list */ static uint8_t rx_ant_id[] = {0, 1, 2, 4, 5, 6, 8, 9, 10}; #if UWB_RADAR_PULSE_PERIOD == 4 && OVERLAY_FRAME_LENGTH != 256 #error "Pulse period and Frame length are not match" #endif static struct UWB_RADAR_T default_radar_cfg = { .channel_num = 9, .rx_gain_level = 14, .lna_gain_level = 5, .pulse_period = UWB_RADAR_PULSE_PERIOD_64NS, .bandwidth = 0x02, .ant_id = UWB_RX_ANT_0, .sts_len = UWB_RADAR_STS_SEGLEN64, .tx_power_level = 46, }; struct reg_tmp_stored { #define STORE_REG_COUNT_MAX 40 #define STORE_REG 0 #define STORE_VAL 1 uint32_t magic; uint32_t reg_count; uint32_t reg_store[STORE_REG_COUNT_MAX][2]; }; static struct reg_tmp_stored reg_save; static uint32_t calibration_peak_idx = 0; #if 1 static int16_t allones[N_SNAPSHOTS] __attribute__((aligned(4))); #else static int16_t allones[512] = { 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, }; #endif /** * \fn * \brief calculate the average of complex input data * * \param [in] data_in Input data * \param [in] data_size Half length of input data * \param [out] data_out Output data */ static void average_data_calc_complex_int(const int32_t *data_in, uint32_t data_size, float *data_out) { int dout_i = 0; int dout_q = 0; for (uint32_t index = 0; index < data_size; index++) { dout_i += data_in[2 * index]; dout_q += data_in[2 * index + 1]; } data_out[0] = (float)dout_i / (float)data_size; data_out[1] = (float)dout_q / (float)data_size; } #if UWB_RADAR_1TNR_MODE == 1 /* * This module will do the following functions: * 1) Take the I/Q input and remove DC component * 2) accumulate the pulses */ static void radar_output_1tnr_one_pulse(const int32_t *data_input, uint32_t data_in_len, float *data_output, uint32_t pulse_period_points) { /* Temporary storage of accumulated monopulse results * The supported pulse length 16/32/64/128/256 samples */ int32_t period_samples[OUT_FRAME_LEN]; float period_samples_out[OUT_FRAME_LEN]; uint32_t pulse_period_num = data_in_len / pulse_period_points; int32_t data_i; int32_t data_q; float data_avg[2]; const int32_t *data_in; float *data_out; // LOG_INFO(TRACE_MODULE_APP, "Pulse period points %d period number %d\r\n", pulse_period_points, pulse_period_num); for (uint8_t n = 0; n < UWB_RADAR_RX_PORT_NUM; n++) { data_in = &data_input[n * data_in_len * 2]; data_out = &data_output[n * pulse_period_points * 2]; // Step1 - accumulate the pulses for (uint32_t i = 0; i < pulse_period_points; i++) { data_i = 0; data_q = 0; for (uint32_t j = 0; j < pulse_period_num; j++) { data_i += data_in[i * 2 + pulse_period_points * 2 * j]; data_q += data_in[i * 2 + pulse_period_points * 2 * j + 1]; } period_samples[i * 2] = data_i; period_samples[i * 2 + 1] = data_q; } /* Step2 - calculate the DC component */ average_data_calc_complex_int(period_samples, pulse_period_points, data_avg); // LOG_INFO(TRACE_MODULE_APP, "DC %f %f\r\n", data_avg[0], data_avg[1]); /* Step3 - remove DC component, Search peak index */ for (uint32_t i = 0; i < pulse_period_points; i++) { period_samples_out[i * 2] = (float)period_samples[i * 2] - data_avg[0]; period_samples_out[i * 2 + 1] = (float)period_samples[i * 2 + 1] - data_avg[1]; } #if 0 float tmp_val; float peak_val = 0.0; if (!calibration_peak_idx) { /* Step3 Search peak index : I^2 + Q^2*/ lsp_mult_f32(period_samples_out, period_samples_out, data_out, pulse_period_points * 2); for (uint32_t i = 0; i < pulse_period_points; i++) { tmp_val = data_out[i * 2] + data_out[i * 2 + 1]; if (tmp_val > peak_val) { peak_val = tmp_val; calibration_peak_idx = (uint16_t)i; } } calibration_peak_idx = calibration_peak_idx - ((calibration_peak_idx - 4) % 8); LOG_INFO(TRACE_MODULE_APP, "ANT%d Raw max index %d\n", n, calibration_peak_idx); } #endif /* Step4 - Peak translation, it takes 22us */ for (uint32_t i = 0; i < pulse_period_points; i++) { uint32_t idx = ((pulse_period_points - calibration_peak_idx + i) > (pulse_period_points - 1)) ? (i - calibration_peak_idx) : (pulse_period_points - calibration_peak_idx + i); data_out[idx * 2] = period_samples_out[i * 2]; data_out[idx * 2 + 1] = period_samples_out[i * 2 + 1]; } } } /* * 128 samples are a group, used for pulse accumulation * The 64K I/Q data in the upper half is from PORT 1, * and the 64K I/Q data in the lower half is from PORT 0. */ static void radar_1tnr_raw_data_preprocess(enum UWB_RADAR_STS_SEGLEN_T sts_seg_len, uint32_t *data_in, int32_t *data_out) { // 64k I/Q data int16_t samp_array_d1[512]; // 512 samples (I and Q) for first data in the word int16_t samp_array_d2[512]; // 512 samples (I and Q) for second data in the word uint32_t data_read = 0; uint32_t offset = 0; uint32_t acc_columns = (uint32_t)ACCUMULATE_ROWS(sts_seg_len) >> (UWB_RADAR_RX_PORT_NUM - 1); uint32_t *mem_data; int32_t *acc_out; /* Port 2 |Port 1 |Port 0 | 1 5.....|1 5.....|1 5.............| 32KB 2 6.....|2 6.....|2 6.............| 32KB 3 7.....|3 7.....|3 7.............| 32KB 4 8.....|4 8.....|4 8.............| 32KB */ // 8KW each block uint32_t seg_in_blk = 1024 * 8; if ((sts_seg_len == UWB_RADAR_STS_SEGLEN64) || (sts_seg_len == UWB_RADAR_STS_SEGLEN32)) { seg_in_blk = seg_in_blk >> (UWB_RADAR_RX_PORT_NUM - 1); if (seg_in_blk < 1024 * 2) { return; } } else { return; } for (uint8_t i = 0; i < UWB_RADAR_RX_PORT_NUM; i++) { mem_data = &data_in[seg_in_blk * (UWB_RADAR_RX_PORT_NUM - 1 - i)]; acc_out = &data_out[i * OVERLAY_FRAME_LENGTH * 2]; /* Outer loop for the 4 banks, each bank will have 32 kbytes or 8 kwords */ for (uint32_t blocks = 0; blocks < BANK_NUM; blocks++) { offset = blocks * 1024 * 8; /* Inner loop for words in that bank, each word has 2 samples (IQ) */ /* 1 snapshot will be 16 words, so accumulate every 16 words */ for (uint32_t columns = 0; columns < OVERLAY_FRAME_LENGTH / BANK_NUM / 2; columns++) { /* Remove head 4KB and tail 2KB */ for (uint32_t rows = CUT_OFF_LINES(HEAD_LEN); rows < (acc_columns - CUT_OFF_LINES(TAIL_LEN)); rows++) { data_read = mem_data[offset + rows * (OVERLAY_FRAME_LENGTH / BANK_NUM / 2) + columns]; // Extract two samples from this word samp_array_d1[rows] = (int16_t)((data_read) & (0xffff)); samp_array_d2[rows] = (int16_t)((data_read >> (16)) & (0xffff)); } /* Accumulate across snapshots , complex so will output 2 values */ lsp_cmplx_inner_product_int8((const int8_t *)&samp_array_d1[CUT_OFF_LINES(HEAD_LEN)], (const int8_t *)allones, (int32_t *)(acc_out + (4 * (BANK_NUM * columns + blocks))), (acc_columns - CUT_OFF_LINES(HEAD_LEN) - CUT_OFF_LINES(TAIL_LEN)), 0); lsp_cmplx_inner_product_int8((const int8_t *)&samp_array_d2[CUT_OFF_LINES(HEAD_LEN)], (const int8_t *)allones, (int32_t *)(acc_out + (4 * (BANK_NUM * columns + blocks) + 2)), (acc_columns - CUT_OFF_LINES(HEAD_LEN) - CUT_OFF_LINES(TAIL_LEN)), 0); } } } } #else /* * This module will do the following functions: * 1) Take the I/Q input and remove DC component * 2) accumulate the pulses */ static void radar_output_one_pulse(const int32_t *data_in, uint32_t data_in_len, float *data_out, uint32_t pulse_period_points) { /* Temporary storage of accumulated monopulse results * The supported pulse length 16/32/64/128/256 samples */ int32_t period_samples[OUT_FRAME_LEN]; float period_samples_out[OUT_FRAME_LEN]; uint32_t pulse_period_num = data_in_len / pulse_period_points; int32_t data_i; int32_t data_q; float data_avg[2]; // LOG_INFO(TRACE_MODULE_APP, "Pulse period points %d period number %d\r\n", pulse_period_points, pulse_period_num); // Step1 - accumulate the pulses for (uint32_t i = 0; i < pulse_period_points; i++) { data_i = 0; data_q = 0; for (uint32_t j = 0; j < pulse_period_num; j++) { data_i += data_in[i * 2 + pulse_period_points * 2 * j]; data_q += data_in[i * 2 + pulse_period_points * 2 * j + 1]; } period_samples[i * 2] = data_i; period_samples[i * 2 + 1] = data_q; } /* Step2 - calculate the DC component */ average_data_calc_complex_int(period_samples, pulse_period_points, data_avg); // LOG_INFO(TRACE_MODULE_APP, "DC %f %f\r\n", data_avg[0], data_avg[1]); /* Step3 - remove DC component, Search peak index */ for (uint32_t i = 0; i < pulse_period_points; i++) { period_samples_out[i * 2] = (float)period_samples[i * 2] - data_avg[0]; period_samples_out[i * 2 + 1] = (float)period_samples[i * 2 + 1] - data_avg[1]; } #if 0 float tmp_val; float peak_val = 0.0; if (!calibration_peak_idx) { /* Step3 - Search peak index : I^2 + Q^2*/ lsp_mult_f32(period_samples_out, period_samples_out, data_out, pulse_period_points * 2); for (uint32_t i = 0; i < pulse_period_points; i++) { tmp_val = data_out[i * 2] + data_out[i * 2 + 1]; if (tmp_val > peak_val) { peak_val = tmp_val; calibration_peak_idx = i; } } LOG_INFO(TRACE_MODULE_APP, "Raw max index %d\r\n", calibration_peak_idx); } #endif /* Step4 - Peak translation, it takes 22us */ for (uint32_t i = 0; i < pulse_period_points; i++) { uint32_t idx = ((pulse_period_points - calibration_peak_idx + i) > (pulse_period_points - 1)) ? (i - calibration_peak_idx) : (pulse_period_points - calibration_peak_idx + i); data_out[idx * 2] = period_samples_out[i * 2]; data_out[idx * 2 + 1] = period_samples_out[i * 2 + 1]; } } static void radar_raw_data_preprocess(enum UWB_RADAR_STS_SEGLEN_T sts_seg_len, uint32_t *mem_data, int32_t *accum_out) { int16_t samp_array_d1[512]; // 512 samples (I and Q) for first data in the word int16_t samp_array_d2[512]; // 512 samples (I and Q) for second data in the word uint32_t data_read = 0; uint32_t offset = 0; uint32_t acc_columns = (uint32_t)ACCUMULATE_ROWS(sts_seg_len); /* Outer loop for the 4 banks, each bank will have 32 kbytes or 8 kwords */ for (uint32_t blocks = 0; blocks < BANK_NUM; blocks++) { offset = blocks * 1024 * 8; /* Inner loop for words in that bank, each word has 2 samples (IQ) */ /* 1 snapshot will be (OVERLAY_FRAME_LENGTH / BANK_NUM / 2) words, so accumulate every (OVERLAY_FRAME_LENGTH / BANK_NUM / 2) words */ for (uint32_t columns = 0; columns < OVERLAY_FRAME_LENGTH / BANK_NUM / 2; columns++) { /* Discard the first 4KB data and the end 2KB data */ for (uint32_t rows = CUT_OFF_LINES(HEAD_LEN); rows < acc_columns - CUT_OFF_LINES(TAIL_LEN); rows++) { data_read = mem_data[offset + rows * (OVERLAY_FRAME_LENGTH / BANK_NUM / 2) + columns]; // Extract two samples from this word samp_array_d1[rows] = (int16_t)((data_read) & (0xffff)); samp_array_d2[rows] = (int16_t)((data_read >> (16)) & (0xffff)); } /* Accumulate across up to 512 snapshots , complex so will output 2 values */ lsp_cmplx_inner_product_int8((const int8_t *)&samp_array_d1[CUT_OFF_LINES(HEAD_LEN)], (const int8_t *)allones, (int32_t *)((uint32_t)accum_out + (16 * (BANK_NUM * columns + blocks))), acc_columns - CUT_OFF_LINES(HEAD_LEN) - CUT_OFF_LINES(TAIL_LEN), 0); lsp_cmplx_inner_product_int8((const int8_t *)&samp_array_d2[CUT_OFF_LINES(HEAD_LEN)], (const int8_t *)allones, (int32_t *)((uint32_t)accum_out + (16 * (BANK_NUM * columns + blocks) + 8)), acc_columns - CUT_OFF_LINES(HEAD_LEN) - CUT_OFF_LINES(TAIL_LEN), 0); } } } #endif void radar_data_process(uint32_t *raw_data_addr, float *data_out, uint16_t *data_len) { // ASSERT(raw_data_addr != NULL, "raw data address invalid"); // ASSERT(data_out != NULL, "data output address invalid"); // ASSERT(data_len != NULL, "data length address invalid"); #if UWB_RADAR_1TNR_MODE == 1 int32_t accum_out[UWB_RADAR_RX_PORT_NUM * OVERLAY_FRAME_LENGTH * 2]; radar_1tnr_raw_data_preprocess(default_radar_cfg.sts_len, raw_data_addr, accum_out); radar_output_1tnr_one_pulse(accum_out, OVERLAY_FRAME_LENGTH, data_out, PULSE_PERIOD_POINTS(default_radar_cfg.pulse_period)); *data_len = (uint16_t)(PULSE_PERIOD_POINTS(default_radar_cfg.pulse_period) * 2 * 4 * UWB_RADAR_RX_PORT_NUM); #else int32_t accum_out[OVERLAY_FRAME_LENGTH * 2]; radar_raw_data_preprocess(default_radar_cfg.sts_len, raw_data_addr, accum_out); radar_output_one_pulse(accum_out, OVERLAY_FRAME_LENGTH, data_out, PULSE_PERIOD_POINTS(default_radar_cfg.pulse_period)); *data_len = (uint16_t)(PULSE_PERIOD_POINTS(default_radar_cfg.pulse_period) * 2 * 4); #endif } void radar_config(struct UWB_RADAR_T *radar_cfg) { ASSERT(radar_cfg != NULL, "radar_cfg address invalid"); default_radar_cfg.request = radar_cfg->request; default_radar_cfg.ant_id = radar_cfg->ant_id; default_radar_cfg.bandwidth = radar_cfg->bandwidth; default_radar_cfg.channel_num = radar_cfg->channel_num; default_radar_cfg.lna_gain_level = radar_cfg->lna_gain_level; default_radar_cfg.rx_gain_level = radar_cfg->rx_gain_level; default_radar_cfg.tx_power_level = radar_cfg->tx_power_level; default_radar_cfg.sts_len = radar_cfg->sts_len; default_radar_cfg.pulse_period = radar_cfg->pulse_period; default_radar_cfg.ranging_tx_power_level = radar_cfg->ranging_tx_power_level; #if UWB_RADAR_2G_MODE_EN calibration_peak_idx = peak_idx_table[default_radar_cfg.pulse_period][DISCARD_SYMBOLS - 24]; #else calibration_peak_idx = peak_idx_table[default_radar_cfg.pulse_period][DISCARD_SYMBOLS - 12]; #endif // LOG_INFO(TRACE_MODULE_APP | TRACE_NO_OPTION, "Raw max index %d\n", calibration_peak_idx); // 1T1R mode, the ant id can be configured from host rx_ant_id[0] = default_radar_cfg.ant_id; // Initialize for (int kk = 0; kk < N_SNAPSHOTS; kk++) { allones[kk] = 0x0001; } LOG_INFO(TRACE_MODULE_APP, "STS len %u Frame len %u N_SNAPSHOTS %u\r\n", 16 << default_radar_cfg.sts_len, OVERLAY_FRAME_LENGTH, N_SNAPSHOTS); } int radar_enable(void) { uint32_t val; uint32_t reg; uint32_t sts_key; switch (default_radar_cfg.pulse_period) { case UWB_RADAR_PULSE_PERIOD_16NS: sts_key = 0x00000000; break; case UWB_RADAR_PULSE_PERIOD_32NS: sts_key = 0x55555555; break; case UWB_RADAR_PULSE_PERIOD_64NS: sts_key = 0xEEEEEEEE; break; case UWB_RADAR_PULSE_PERIOD_128NS: sts_key = 0xFEFEFEFE; break; case UWB_RADAR_PULSE_PERIOD_256NS: sts_key = 0xFFFEFFFE; break; } /**************************************SYS RADIO REG*********************************************/ reg = 0x40000404; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count = 1; val = val & ~0xF0000U; #if UWB_RADAR_2G_MODE_EN // Set LPF_BW 500M | RX ADC sample rate 2Gs/s | pulse width 0:2ns(500M), 1:0.92ns(1G), 2:0.75ns(1.3G) val |= ((1U << 18) | ((default_radar_cfg.bandwidth & 0x3U) << 16)); #else // Set LPF_BW 250M | RX ADC sample rate 1Gs/s | pulse width 0:2ns(500M), 1:0.92ns(1G), 2:0.75ns(1.3G) val |= ((1U << 19) | ((default_radar_cfg.bandwidth & 0x3U) << 16)); #endif REG_WRITE(reg, val); // LO calibrate REG_WRITE(0x40006000, 0x80000400); while ((REG_READ(0x40006004) & 0x00000008) == 0) { } reg = 0x40000628; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Set rx antenna REG_WRITE(0x40000628, (1 << 6) | rx_ant_code[default_radar_cfg.ant_id]); /*****************MAC config********************/ reg = 0x5000A004; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // The loopback function must be enabled in MK8000 radar mode REG_WRITE(reg, 0x18C); reg = 0x5000A044; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Mac SIFS 1.6us = 0x64 * 16ns REG_WRITE(reg, 0x640064); /**********************************************/ // val = REG_READ(0x4000002C); // REG_WRITE(0x4000002C, val | (1 << 30) | (1 << 25)); reg = 0x40000608; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // LPF ADC LPF_BN bias current %50 val = REG_READ(0x40000608); val |= 0x4U; REG_WRITE(reg, val); reg = 0x40000700; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Disable RX AGC, and use register to configure the gain of LNA and filter; val = (1U << 31) | ((default_radar_cfg.rx_gain_level & 0x1FU) << 16) | (default_radar_cfg.lna_gain_level & 0x7U); REG_WRITE(reg, val); /******************************************TXBE REG*********************************************/ /* These four parameters are compatible with ranging mode * ### trx mode 15.4z bprf * ### Channel NUM, Channel switching will involve reconfiguration of transmit power * ### MEAN_PRF_64M * ### Data bit rate 6.8M */ // Set tx Preamble length 16, sfd 8 reg = 0x40001000; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // set preamble length 16 val = 0x20E368; // clear tx preamble length and SFD length val = val & ~((0x7U << 10) | (0x3FU << 13) | (0x7U << 20)); // SFD length 8, Mean prf 64M val |= (0x7U << 13) | (0x2U << 20); REG_WRITE(reg, val); reg = 0x40001008; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Set sts tx segment length 16/32/64 // clear tx STS_SEGNUM and STS_SEGLEN and EN_CUST_STS val = val & ~((0x3U << 4) | (0x7U << 6) | (0x1U << 9)); // set sts segment length and customized sts bit val |= ((0x1U << 9) | (default_radar_cfg.sts_len << 6)); REG_WRITE(reg, val); reg = 0x4000103C; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Set STS polarity of 1 and 0 REG_WRITE(reg, (0x1U << 5)); reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x4000101C; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x4000101C); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40001020; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40001020); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40001024; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40001024); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40001028; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40001028); reg_save.reg_count++; /// TXSTSKEY REG_WRITE(0x4000101C, sts_key); REG_WRITE(0x40001020, sts_key); REG_WRITE(0x40001024, sts_key); REG_WRITE(0x40001028, sts_key); reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x4000100C; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x4000100C); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40001010; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40001010); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40001014; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40001014); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40001018; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40001018); reg_save.reg_count++; REG_WRITE(0x4000100C, 0x0); REG_WRITE(0x40001010, 0x0); REG_WRITE(0x40001014, 0x0); REG_WRITE(0x40001018, 0x0); /******************************************RXBE REG*********************************************/ reg = 0x40002000; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; val = 0x72814U; // Clear tx STS_SEGNUM and STS_SEGLEN and EN_CUST_STS val = val & ~(0x7U << 10); // Set rx sts len, Customized sts bit val |= ((default_radar_cfg.sts_len << 10) | (0x1U << 13)); REG_WRITE(reg, val); reg = 0x40002004; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Off main tap phase compensation val |= (0x1U << 27); REG_WRITE(reg, val); #define RX_DUMP_EN 1 #define DUMP_IQ_AFTER_RX_CTRL 1 /* IQ data after rx_ctrl 64bit 500M 7bit */ #define DUMP_IQ_BEFORE_RX_CTRL 2 /* IQ data before rx_ctrl 64bit 500M 7bit */ #define DUMP_IQ_DS2 3 /* IQ data after DS2 64bit 500M 8bit */ #define DUMP_IQ_DS1 4 /* IQ data after DS1 128bit 1G 8bit */ #define DUMP_I_2G_ADC 5 /* I component data from ADC 128bit 2G 7bit */ #define DUMP_Q_2G_ADC 6 /* Q component data from ADC 128bit 2G 7bit */ #define DUMP_POS_STS 0 /* 0 : Dump STS */ #define DUMP_POS_RXEN 1 /* 1 : rxen */ #define DUMP_POS_BURST_DETECTION 2 /* 2 : burst detection */ #define DUMP_POS_PHR 3 /* 3 : phr */ #define TRUNC_MODE 0 reg = 0x40002040; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Set rx debug reg #if UWB_RADAR_2G_MODE_EN val = (uint32_t)((DUMP_IQ_DS1 & 0x7) | ((DUMP_POS_RXEN & 0x3) << 3) | ((TRUNC_MODE & 0x1) << 5) | (RX_DUMP_EN << 7) | ((DISCARD_SYMBOLS & 0xfff) << 8)); #else val = (uint32_t)((DUMP_IQ_DS2 & 0x7) | ((DUMP_POS_RXEN & 0x3) << 3) | ((TRUNC_MODE & 0x1) << 5) | (RX_DUMP_EN << 7) | ((DISCARD_SYMBOLS & 0xfff) << 8)); #endif REG_WRITE(reg, val); reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40002028; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40002028); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x4000202C; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x4000202C); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40002030; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40002030); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40002034; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40002034); reg_save.reg_count++; /// RXSTSKEY REG_WRITE(0x40002028, sts_key); REG_WRITE(0x4000202C, sts_key); REG_WRITE(0x40002030, sts_key); REG_WRITE(0x40002034, sts_key); reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40002018; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40002018); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x4000201C; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x4000201C); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40002020; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40002020); reg_save.reg_count++; reg_save.reg_store[reg_save.reg_count][STORE_REG] = 0x40002024; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = REG_READ(0x40002024); reg_save.reg_count++; REG_WRITE(0x40002018, 0x0); REG_WRITE(0x4000201C, 0x0); REG_WRITE(0x40002020, 0x0); REG_WRITE(0x40002024, 0x0); /******************************************RXFE REG*********************************************/ reg = 0x40003040; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Disable enAGC val &= 0xFFFFFFFE; REG_WRITE(reg, val); /******************************************SYNC REG*********************************************/ reg = 0x40004048; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // clear SFD length val = val & ~0xFFU; // set SFD length 8 val |= 0xBU; REG_WRITE(reg, val); reg = 0x40004054; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Burst detection absolution threshold to set maximum,no synchronization val |= 0x1FFFFFU; REG_WRITE(reg, val); /******************************************RXFE REG*********************************************/ reg = 0x40003020; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; // Disable PLL(disable CFO loop and TO loop) val |= 0x3U; REG_WRITE(reg, val); reg = 0x40003034; val = REG_READ(reg); reg_save.reg_store[reg_save.reg_count][STORE_REG] = reg; reg_save.reg_store[reg_save.reg_count][STORE_VAL] = val; reg_save.reg_count++; #if UWB_RADAR_2G_MODE_EN // Set 2G ADC sampling input REG_WRITE(reg, 0); #else // Set 1G ADC sampling input REG_WRITE(reg, 1); #endif /******************************************SYS REG*********************************************/ if (default_radar_cfg.ranging_tx_power_level != default_radar_cfg.tx_power_level) { uwb_tx_power_set(default_radar_cfg.tx_power_level); } reg_save.magic = 0; for (uint32_t i = 0; i < reg_save.reg_count; i++) { reg_save.magic ^= reg_save.reg_store[i][STORE_REG]; reg_save.magic ^= reg_save.reg_store[i][STORE_VAL]; } // LOG_INFO(TRACE_MODULE_DRIVER, "%d reg val stored, magic %x\r\n", reg_save.reg_count, reg_save.magic); // enable dump mode phy_dump_en(1); return 0; } int radar_disable(void) { phy_dump_en(0); ASSERT(reg_save.reg_count < STORE_REG_COUNT_MAX, "The number of radar registers stored is overwritten"); uint32_t val = 0; for (uint32_t i = 0; i < reg_save.reg_count; i++) { val ^= reg_save.reg_store[i][STORE_REG]; val ^= reg_save.reg_store[i][STORE_VAL]; } ASSERT(val == reg_save.magic, "Radar Storage content is overwritten"); // recovery site for (uint32_t j = 0; j < reg_save.reg_count; j++) { REG_WRITE(reg_save.reg_store[j][STORE_REG], reg_save.reg_store[j][STORE_VAL]); } if (default_radar_cfg.ranging_tx_power_level != default_radar_cfg.tx_power_level) { uwb_tx_power_set(default_radar_cfg.ranging_tx_power_level); } return 0; } void radar_start(uint8_t ant_idx) { uint32_t lock = int_lock(); uwb_rx_antenna_open((enum UWB_RX_ANT_T)rx_ant_id[ant_idx]); // enter debuge mode enter_debug_mode(); #if UWB_RADAR_1TNR_MODE == 1 static uint32_t loopback_anchor_point; uint32_t rx_win = US_TO_PHY_TIMER_COUNT(UWB_RADAR_RX_WINDOW); uint32_t sts_len = UWB_RADAR_STS_LENGTH; if (ant_idx == 0) { loopback_anchor_point = REG_READ(0x40000418) + US_TO_PHY_TIMER_COUNT(UWB_RADAR_PREFETCH_TIME); } else if (ant_idx == 1) { rx_win = US_TO_PHY_TIMER_COUNT(UWB_RADAR_RX_WINDOW2); sts_len = (sts_len >= 1) ? sts_len - 1 : 0; } else if (ant_idx == 2) { rx_win = US_TO_PHY_TIMER_COUNT(UWB_RADAR_RX_WINDOW3); sts_len = (sts_len >= 2) ? sts_len - 2 : 0; } uint32_t target = loopback_anchor_point + US_TO_PHY_TIMER_COUNT(FRAME_INTERVAL * ant_idx); // Delay discard_symbols, dump data uint32_t val = (uint32_t)(4 | (1 << 3) | (1 << 7) | ((DISCARD_SYMBOLS & 0xfff) << 8)); REG_WRITE(0x40002040, val); // TXSTS val = REG_READ(0x40001008); // clear sts seglen val = val & ~(0x7U << 6); // STS_SEGLEN val |= (sts_len << 6); REG_WRITE(0x40001008, val); // RXSTS val = REG_READ(0x40002000); // clear sts seglen val = val & ~(0x7U << 10); // STS_SEGLEN val |= (sts_len << 10); REG_WRITE(0x40002000, val); // Rx Timeout REG_WRITE(0x40000408, target + rx_win); mac_tx(EVT_MODE_MAC_ASAP_PHY_FIX, target & 0xFFFFFFFC, 0, NULL, 0); mac_start(); #else #if 0 mac_tx(EVT_MODE_MAC_PHY_ASAP, 0, 0, NULL, 0); // reset DPTX DPRX SYSCON->SYS_RMU &= ~((1U << 25) | (1U << 24)); SYSCON->SYS_RMU |= ((1U << 25) | (1U << 24)); // Rx Timeout REG_WRITE(0x40000408, REG_READ(0x40000418) + US_TO_PHY_TIMER_COUNT(UWB_RADAR_RX_WINDOW)); // sw trigger <==> void mac_start(void) REG_WRITE(0x5000A01C, 1); #else uint32_t target = REG_READ(0x40000418) + US_TO_PHY_TIMER_COUNT(UWB_RADAR_PREFETCH_TIME); // Rx Timeout REG_WRITE(0x40000408, target + US_TO_PHY_TIMER_COUNT(UWB_RADAR_RX_WINDOW)); mac_tx(EVT_MODE_MAC_ASAP_PHY_FIX, target & 0xFFFFFFFC, 0, NULL, 0); mac_start(); #endif #endif int_unlock(lock); }