chen
2024-11-08 cc432b761c884a0bd8e9d83db0a4e26109fc08b1
keil/include/components/app/src/uwb_data_transfer.c
对比新文件
@@ -0,0 +1,669 @@
/*
 * 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_trace.h"
#include "mk_uwb.h"
#include "mk_aes.h"
#include "mk_power.h"
#include "lib_aoa.h"
#include "lib_ranging.h"
#include "uwb_data_transfer.h"
#include "uwb_data.h"
struct RANGING_ENV_T ranging_env;
uint8_t fira_uwb_tx_buf[PHY_PAYLOAD_LEN_MAX];
static struct DATA_TRANSFER_CB_T data_transfer_cb;
static struct UWB_OP_T op = {
    .session_configure = data_transfer_configure,
    .session_start = data_transfer_start,
    .session_stop = data_transfer_stop,
    .session_local_addr_set = ranging_local_addr_set,
    .session_peer_addr_set = ranging_peer_addr_set,
    .session_responder_addr_add = ranging_responder_addr_add,
    .session_responder_list_clr = ranging_responder_list_clr,
    .session_responder_num_get = ranging_responder_num_get,
    .session_responder_addr_get = ranging_responder_addr_get,
    .session_dynamic_update_responder_list = NULL,
    .session_set_ccc_ursk = NULL,
    .vendor_session_configure = NULL,
    .vendor_session_start = NULL,
    .vendor_session_stop = NULL,
};
static void data_transfer_tx_process(struct MAC_HW_REPORT_T *tx_report);
static void data_transfer_rx_process(struct MAC_HW_REPORT_T *rx_report);
void app_session_init(void);
//------------------------------------------------------------------------------
int data_transfer_init(uint8_t handle_id)
{
    /* store handler ID */
    data_transfer_cb.handle_id = handle_id;
    /* init rx queue */
    WSF_QUEUE_INIT(&data_transfer_cb.msg_queue);
    LOG_INFO(TRACE_MODULE_APP, "Ranging lib version: %s\r\n", MK8000_get_rangelib_version());
    LOG_INFO(TRACE_MODULE_APP, "AoA lib version: %s\r\n", MK8000_get_aoalib_version());
    return 0;
}
int data_transfer_deinit(void)
{
    return 0;
}
// This function will be called by uwbapi_session_init()
void app_session_init(void)
{
    // register process handler for MAC TX done and RX done
    mac_register_process_handler(data_transfer_tx_process, data_transfer_rx_process);
    uwbs_handler_init(&op);
}
void data_transfer_configure(void)
{
    fira_keys_generate();
    aes_update_key(AES_ID0, &fira_key.devPayKey.ukey.keyByte[0]);
    mac_update_ccm_key((uint32_t *)&fira_key.devPayKey.ukey.keyWord[0]);
    uwb_app_config.ranging_stage = RANGING_IDLE;
    ranging_env.uwb_period_prefetch_time = UWB_PERIOD_PREFETCH_TIME;
    ranging_env.uwb_evt_prefetch_time = UWB_EVT_PREFETCH_TIME;
    ranging_env.uwb_rx_open_in_advance = UWB_RX_OPEN_IN_ADVANCE;
    ranging_env.uwb_rx_window = UWB_RX_WINDOW;
    ranging_env.uwb_rx_open_in_advance_wakeup = UWB_RX_OPEN_IN_ADVANCE;
    ranging_env.uwb_rx_window_wakeup = UWB_RX_WINDOW;
    ranging_env.ranging_period = MS_TO_PHY_TIMER_COUNT(uwb_app_config.session_param.ranging_interval);
    ranging_env.slots_per_block = (uint16_t)(uwb_app_config.session_param.ranging_interval / RSTU_TO_MS(uwb_app_config.session_param.slot_duration));
    ASSERT(ranging_env.slots_per_block >= uwb_app_config.session_param.slots_per_round, "Ranging block parameters configure wrong");
    ranging_env.slot_interval = RSTU_TO_PHY_TIMER_COUNT(uwb_app_config.session_param.slot_duration);
    ranging_env.round_duration = ranging_env.slot_interval * uwb_app_config.session_param.slots_per_round;
    ranging_env.phy_sts_index = fira_key.phyStsIdxInit - ranging_env.slots_per_block;
    ranging_env.enable = 0;
    ranging_env.slot_idx = 0;
    ranging_env.tof = 0;
    ranging_env.range_data.ranging_type = 0x1; // TWR (SS-TWR, DS-TWR)
    ranging_env.range_data.ranging_interval = uwb_app_config.session_param.ranging_interval;
    ranging_env.range_data.mac_addr_mode = uwbs_mac_addr_mode_get();
    ranging_env.range_data.session_id = uwb_app_config.session_id;
    ranging_env.stride_length = uwb_app_config.session_param.stride_length;
    ranging_env.round_offset_in_block = 0;
    ranging_env.next_round_index = 0;
    uwbs_configure(PHY_TX | PHY_RX, uwb_app_config.session_param.tx_power_level);
    // uwb_dm_config(&mdsdu_tx, &mdsdu_rx);
    LOG_INFO(TRACE_MODULE_FIRA, "slot duration %d slots per round %d ranging interval %d\r\n", uwb_app_config.session_param.slot_duration,
             uwb_app_config.session_param.slots_per_round, uwb_app_config.session_param.ranging_interval);
}
void data_transfer_start(void)
{
    ranging_env.enable = 1;
    ranging_env.lost_cnt = 0xFF;
    ranging_env.anchor_point = phy_timer_count_get();
    ranging_env.slot_idx = 0;
    ranging_env.is_hopping = uwb_app_config.session_param.hopping_mode;
    enum DEV_ROLE_T role = uwb_app_config.session_param.device_role;
    if ((role == DEV_ROLE_INITIATOR) || (role == DEV_ROLE_GATE_CONTROLLER))
    {
        uwb_app_config.ranging_stage = RANGING_DTPCM;
        phy_timer_target_set(ranging_env.anchor_point + ranging_env.ranging_period - ranging_env.uwb_period_prefetch_time, session_timer_callback);
        power_mode_request(POWER_UNIT_APP, POWER_MODE_POWER_DOWN);
    }
    else
    {
        ranging_env.is_hopping = 0;
        ranging_env.stride_length = 0;
        ranging_env.round_offset_in_block = 0;
        ranging_env.next_round_index = 0;
        power_on_radio(0, 1);
        uwb_app_config.ranging_stage = RANGING_SYNC;
        phy_sts_pkt_cfg_set(SP0);
        ranging_update_slot_index(ranging_env.slot_idx);
        mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, ranging_env.ranging_period);
        mac_start();
        power_mode_request(POWER_UNIT_APP, POWER_MODE_SLEEP);
    }
    ranging_env.count = 0;
    ranging_env.count_last = 0;
    LOG_INFO(TRACE_MODULE_FIRA, "Ranging start, role %d\r\n", uwb_app_config.session_param.device_role);
}
void data_transfer_stop(void)
{
    ranging_env.enable = 0;
    LOG_INFO(TRACE_MODULE_FIRA, "Ranging stop\r\n");
}
#if 0
/*
bitmap for 1 responder
slot idx:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 ...
TX bitmap: 1  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0 ...
RX bitmap: 0  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1 ...
bitmap for 2 responders
slot idx:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 ...
TX bitmap: 1  1  0  0  1  0  0  1  0  0  1  0  0  1  0  0  1 ...
RX bitmap: 0  0  1  1  0  1  1  0  1  1  0  1  1  0  1  1  0 ...
bitmap for 3 responders
slot idx:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 ...
TX bitmap: 1  1  0  0  0  1  0  0  0  1  0  0  0  1  0  0  0 ...
RX bitmap: 0  0  1  1  1  0  1  1  1  0  1  1  1  0  1  1  1 ...
*/
void uwb_slot_bitmap_generate(uint8_t *bits, uint8_t dev_idx, uint8_t dev_num)
{
    ASSERT(bits, "Input bits is null");
    uint8_t offset = dev_idx;
    uint8_t size = uwb_slot_bitmap_size_get();
    while (offset < size * 8)
    {
        bits[offset >> 3] |= (uint8_t)(1 << (offset & 0x7));
        offset += dev_num;
    }
}
#else
void uwb_slot_bitmap_generate(uint8_t *bits, uint8_t dev_idx, uint8_t dev_num)
{
    ASSERT(bits, "Input bits is null");
    uint8_t size = uwb_slot_bitmap_size_get();
    uint8_t offset = 0;
    int bitValue;
    while (offset < size * 8)
    {
        if (dev_idx == 0)
        {
            bitValue = ((offset + 1) % 3 == 0) ? 0 : 1;
            bits[offset / 8] |= (bitValue << (offset % 8));
        }
        else
        {
            bitValue = ((offset + 1) % 3 == 0) ? 1 : 0;
            bits[offset / 8] |= (bitValue << (offset % 8));
        }
        offset++;
    }
}
#endif
uint8_t uwb_dm_rx_responder_idx(uint8_t slot_idx, uint8_t dev_num)
{
    ASSERT(slot_idx > 1, "RX slot idx is wrong");
    uint8_t dev_idx = (slot_idx - 2) % (dev_num + 1);
    return dev_idx;
}
void uwb_pkt_tx_done_ind(const struct MAC_HW_REPORT_T *tx, enum RANGING_STAGE_T stage, uint8_t slot_idx)
{
#if DM_PRINT_PAYLOAD_EN
    struct UWB_PKT_TX_DONE_IND_T *ind = WsfMsgAlloc(sizeof(struct UWB_PKT_TX_DONE_IND_T) + tx->pkt_len);
#else
    struct UWB_PKT_TX_DONE_IND_T *ind = WsfMsgAlloc(sizeof(struct UWB_PKT_TX_DONE_IND_T));
#endif
    if (ind != NULL)
    {
        ind->hdr.event = UWB_PKT_TX_DONE_MSG;
        ind->ranging_stage = (uint8_t)stage;
        ind->slot_idx = slot_idx;
        ind->status = tx->err_code;
        ind->tx_len = tx->pkt_len;
#if DM_PRINT_PAYLOAD_EN
        if ((ind->tx_len) && (tx->pkt_data != NULL))
        {
            memcpy(ind->tx_data, tx->pkt_data, tx->pkt_len);
        }
#endif
        // Send the message
        WsfMsgSend(data_transfer_cb.handle_id, ind);
    }
    else
    {
        LOG_WARNING(TRACE_MODULE_UWB, "memory is not enough for UWB_PKT_TX_DONE_IND_T\r\n");
    }
}
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
uint16_t uwb_pkt_rx_done_ind(const struct MAC_HW_REPORT_T *rx, enum RANGING_STAGE_T stage, uint8_t slot_idx)
{
    // send an indication to application
#if DM_PRINT_PAYLOAD_EN
    struct UWB_PKT_RX_DONE_IND_T *ind = WsfMsgAlloc(sizeof(struct UWB_PKT_RX_DONE_IND_T) + rx->pkt_len);
#else
    struct UWB_PKT_RX_DONE_IND_T *ind = WsfMsgAlloc(sizeof(struct UWB_PKT_RX_DONE_IND_T));
#endif
    if (ind != NULL)
    {
        ind->hdr.event = UWB_PKT_RX_DONE_MSG;
        ind->ranging_stage = (uint8_t)stage;
        ind->slot_idx = slot_idx;
        ind->status = rx->err_code;
        ind->rssi = rx->rssi;
        ind->snr = rx->snr;
        if (rx->err_code == UWB_RX_OK)
        {
#if 1
            ind->rx_len = rx->pkt_len;
#if DM_PRINT_PAYLOAD_EN
            if ((ind->rx_len) && (rx->pkt_data != NULL))
            {
                memcpy(ind->rx_data, rx->pkt_data, rx->pkt_len);
            }
#endif
#else
            // Decrypt packet
            ind->rx_len = fira_packet_decrypt(rx->pkt_data, ind->rx_data, rx->pkt_len, slot_idx);
            ind->status |= (ind->rx_len ? 0 : UWB_MAC_DEC_ERR);
#endif
        }
        // Send the message
        WsfMsgSend(data_transfer_cb.handle_id, ind);
        return ind->status;
    }
    else
    {
        LOG_WARNING(TRACE_MODULE_UWB, "memory is not enough for UWB_PKT_RX_DONE_IND_T\r\n");
        return 0xFFFF;
    }
}
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic pop
#endif
void session_timer_callback(void *dev, uint32_t time)
{
    // LOG_INFO(TRACE_MODULE_FIRA, "PHY timer slot %d\r\n", ranging_env.slot_idx);
    // board_led_on(BOARD_LED_2);
    if (uwb_app_config.session_param.ranging_round_usage == DATA_TRANSFER_PHASE)
    {
        data_transfer_phy_timer_callback(dev, time);
    }
    // board_led_off(BOARD_LED_2);
}
enum RANGING_STAGE_T session_fsm(const struct MAC_HW_REPORT_T *ind)
{
    // LOG_INFO(TRACE_MODULE_FIRA, "FSM %02x slot %d\r\n", uwb_app_config.ranging_stage, ranging_env.slot_idx);
    // board_led_on(BOARD_LED_1);
    enum RANGING_STAGE_T stage = RANGING_IDLE;
    if (uwb_app_config.session_param.ranging_round_usage == DATA_TRANSFER_PHASE)
    {
        stage = data_transfer_fsm(ind);
    }
    // board_led_off(BOARD_LED_1);
    return stage;
}
static void data_transfer_tx_process(struct MAC_HW_REPORT_T *tx_report)
{
    session_fsm(tx_report);
}
static void data_transfer_rx_process(struct MAC_HW_REPORT_T *rx_report)
{
    session_fsm(rx_report);
}
#if UWB_SERIAL_DATA_TRANSFER_EN
static uint8_t pkt_header_buff[2];
static uint8_t data_buff[SERIAL_MESSAGE_MAX_LEN];
static struct RING_BUFFER_T tx_cb;
static struct RING_BUFFER_T rx_cb;
static void uwb_serial_cb_init(struct RING_BUFFER_T *tx, struct RING_BUFFER_T *rx)
{
    for (int i = 0; i < UWB_SERIAL_DATA_POOL_SIZE; i++)
    {
        tx->buffer[i].flag = true;
        rx->buffer[i].flag = true;
    }
    tx->head = 0;
    tx->tail = 0;
    tx->check = 0;
    rx->head = 0;
    rx->tail = 0;
    rx->check = 0;
    return;
}
static bool uwb_serial_cb_is_full(struct RING_BUFFER_T *cb)
{
    if (cb->buffer[cb->tail].flag == false && ((cb->tail + 1) % (UWB_SERIAL_DATA_POOL_SIZE) == cb->head))
    {
        LOG_WARNING(TRACE_NO_OPTION | TRACE_MODULE_APP, "tx_cb_is_full\r\n");
        return true;
    }
    return false;
}
static struct UWB_TX_MSG_t *uwb_serial_cb_read(struct RING_BUFFER_T *cb)
{
    if (cb->buffer[cb->check].flag == false)
    {
        return &cb->buffer[cb->check];
    }
    return NULL;
}
static void uwb_serial_cb_write(struct RING_BUFFER_T *cb, uint8_t *value, uint16_t length)
{
    if (uwb_serial_cb_is_full(cb))
    {
        LOG_INFO(TRACE_MODULE_APP, "uwb serial data fifo full\r\n");
        return;
    }
    if (cb->buffer[cb->tail].flag == true)
    {
        cb->buffer[cb->tail].flag = false;
        cb->buffer[cb->tail].length = length;
        memcpy(&cb->buffer[cb->tail].msg, value, cb->buffer[cb->tail].length);
#if 0
        LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "serial write FIFO[%d] MSG\r\n", cb->tail);
        for (uint8_t i = 0; i < cb->buffer[cb->tail].length; i++)
        {
            LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "%02x ", cb->buffer[cb->tail].msg[i]);
        }
        LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "\r\n");
#endif
    }
    else
    {
        LOG_INFO(TRACE_MODULE_APP, "uwb fifo block number %d\r\n", cb->tail);
    }
    cb->tail = (cb->tail + 1) % UWB_SERIAL_DATA_POOL_SIZE;
}
void uwb_serial_tx_msg_check(void)
{
    struct UWB_TX_MSG_t *uwb_tx_msg = uwb_serial_cb_read(&tx_cb);
    if (uwb_tx_msg == NULL)
    {
        return;
    }
    if (uwb_dm_tx_is_busy() == 1)
    {
        return;
    }
    if (uwb_tx_msg->flag == false)
    {
        struct DM_MDSDU_T mdsdu_tx;
        mdsdu_tx.mac_addr = ranging_responder_addr_get(0);
        mdsdu_tx.len = uwb_tx_msg->length;
        mdsdu_tx.data = uwb_tx_msg->msg;
        mdsdu_tx.ready = 1;
        uwb_dm_tx_pkt(&mdsdu_tx);
        tx_cb.buffer[tx_cb.check].flag = true;
        tx_cb.check = (tx_cb.check + 1) % UWB_SERIAL_DATA_POOL_SIZE;
        return;
    }
    return;
}
void uwb_serial_rx_msg_update(struct DM_MDSDU_T *rx)
{
    rx_cb.buffer[rx_cb.check].length = rx->len;
    rx_cb.buffer[rx_cb.check].flag = false;
    rx_cb.check = (rx_cb.check + 1) % UWB_SERIAL_DATA_POOL_SIZE;
    uwb_dm_rx_config(rx_cb.buffer[rx_cb.check].msg);
    return;
}
void uwb_serial_rx_msg_check(void)
{
    if (rx_cb.buffer[rx_cb.tail].flag == false)
    {
#if 0
        LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "serial read FIFO[%d] MSG\r\n", rx_cb.tail);
        for (uint8_t i = 0; i < rx_cb.buffer[rx_cb.tail].length; i++)
        {
            LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "%02x ", rx_cb.buffer[rx_cb.tail].msg[i]);
        }
        LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "\r\n");
#endif
        int ret = DRV_OK;
        ret = uart_send(UART_ID1, rx_cb.buffer[rx_cb.tail].msg, rx_cb.buffer[rx_cb.tail].length, 0);
        if (ret != DRV_OK)
        {
            LOG_INFO(TRACE_MODULE_APP, "UART ERROR 0x%02x\r\n", ret);
        }
        else
        {
            rx_cb.buffer[rx_cb.tail].flag = true;
            rx_cb.tail = (rx_cb.tail + 1) % UWB_SERIAL_DATA_POOL_SIZE;
        }
    }
    return;
}
static void serial_receive_callback(void *dev, uint32_t err_code)
{
    uint32_t lock = int_lock();
    volatile static uint16_t tmp_read_idx = 0;
    if (tmp_read_idx == 0)
    {
        uint16_t sum_bytes = (uint16_t)((pkt_header_buff[1] << 8) + (pkt_header_buff[0]));
        ASSERT(sum_bytes <= SERIAL_MESSAGE_MAX_LEN, "Frame length is over range %u", sum_bytes);
        tmp_read_idx = sum_bytes;
        uart_receive(UART_ID1, data_buff, sum_bytes, serial_receive_callback);
    }
    else
    {
#if 0
        LOG_INFO(TRACE_MODULE_APP, "serial recv bytes [%d]\r\n",tmp_read_idx);
        for (uint8_t i = 0; i < tmp_read_idx; i++)
        {
            LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "%02x ", data_buff[i]);
        }
        LOG_INFO(TRACE_NO_OPTION | TRACE_MODULE_APP, "\r\n");
#endif
        if (tmp_read_idx <= MDSDU_MTU_MAX)
        {
            uwb_serial_cb_write(&tx_cb, data_buff, tmp_read_idx);
        }
        else
        {
            while (tmp_read_idx >= MDSDU_MTU_MAX)
            {
                uwb_serial_cb_write(&tx_cb, data_buff, MDSDU_MTU_MAX);
                tmp_read_idx -= MDSDU_MTU_MAX;
            }
            uwb_serial_cb_write(&tx_cb, &data_buff[MDSDU_MTU_MAX], tmp_read_idx);
        }
        tmp_read_idx = 0;
    }
    if (tmp_read_idx == 0)
    {
        uart_receive(UART_ID1, pkt_header_buff, sizeof(pkt_header_buff), serial_receive_callback);
    }
    int_unlock(lock);
}
void uwb_serial_data_transfer_init(void)
{
    LOG_INFO(TRACE_MODULE_APP, "UART input data format: Length(2B) + Data \r\n");
    struct UART_CFG_T serialuwb_cfg = {
        .parity = UART_PARITY_NONE,
        .stop = UART_STOP_BITS_1,
        .data = UART_DATA_BITS_8,
        .flow = UART_FLOW_CONTROL_NONE,
        .rx_level = UART_RXFIFO_CHAR_1,
        .tx_level = UART_TXFIFO_EMPTY,
        .baud = BAUD_921600,
        .dma_en = true,
        .int_rx = false,
        .int_tx = false,
    };
    uart_open(UART_ID1, &serialuwb_cfg);
    uwb_serial_cb_init(&tx_cb, &rx_cb);
    uwb_dm_rx_config(rx_cb.buffer[rx_cb.head].msg);
    uart_receive(UART_ID1, pkt_header_buff, sizeof(pkt_header_buff), serial_receive_callback);
    return;
}
#else
#include "mk_timer.h"
static uint8_t tx_buff[1024];
static uint8_t rx_buff[1024];
static uint16_t length = 977;
static void data_gen(uint16_t len)
{
    uint16_t offset = 0;
    while (len)
    {
        for (uint8_t i = 0; i < 255; i++)
        {
            if (len == 0)
            {
                break;
            }
            tx_buff[offset++] = i;
            len--;
        }
    }
}
void uwb_data_transfer_send_test(void)
{
    struct DM_MDSDU_T mdsdu_tx;
    mdsdu_tx.mac_addr = ranging_responder_addr_get(0);
    mdsdu_tx.len = length;
    mdsdu_tx.data = tx_buff;
    mdsdu_tx.ready = 1;
    uwb_dm_tx_pkt(&mdsdu_tx);
    return;
}
static void timer_callback(void *dev, uint32_t time)
{
    uwb_data_transfer_send_test();
}
void uwb_data_transfer_init_test(void)
{
    if (uwb_app_config.session_param.device_role == DEV_ROLE_INITIATOR)
    {
        data_gen(length);
        struct TIMER_CFG_T timer_cfg = {
            .extin_type = TIMER_EXTIN_NONE,
            .load = 0x7A12,
            .int_en = true,
            .callback = timer_callback,
        };
        timer_open(TIMER_ID0, &timer_cfg);
    }
    uwb_dm_rx_config(rx_buff);
    return;
}
#endif