chen
2024-11-08 cc432b761c884a0bd8e9d83db0a4e26109fc08b1
keil/include/components/app/src/ul_tdoa.c
对比新文件
@@ -0,0 +1,402 @@
/*
 * 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_power.h"
#include "mk_uwb.h"
#include "mk_clock.h"
#include "uwb_api.h"
#include "ul_tdoa.h"
#include "lib_ranging.h"
#include "lib_aoa.h"
#include "mk_trng.h"
#include <stdlib.h>
struct UL_TDOA_ENV_T ul_tdoa_env;
static struct UL_TDOA_CB_T ul_tdoa_cb;
static struct UWB_OP_T op = {
    .session_configure = ul_tdoa_configure,
    .session_start = ul_tdoa_start,
    .session_stop = ul_tdoa_stop,
    .session_local_addr_set = uwbs_local_short_addr_set,
    .session_peer_addr_set = NULL,
    .session_responder_addr_add = NULL,
    .session_responder_list_clr = NULL,
    .session_dynamic_update_responder_list = NULL,
    .session_set_ccc_ursk = NULL,
};
static void ul_tdoa_timer_callback(void *dev, uint32_t time);
static uint8_t tx_msg[127] = {0};
static uint16_t tx_msg_len = 0;
static void ul_tdoa_tx_process(struct MAC_HW_REPORT_T *tx_report);
static void ul_tdoa_rx_process(struct MAC_HW_REPORT_T *rx_report);
void app_session_init(void);
int ul_tdoa_init(uint8_t handle_id)
{
    /* store handler ID */
    ul_tdoa_cb.handle_id = handle_id;
    /* init rx queue */
    WSF_QUEUE_INIT(&ul_tdoa_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 ul_tdoa_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(ul_tdoa_tx_process, ul_tdoa_rx_process);
    uwbs_handler_init(&op);
}
void ul_tdoa_configure(void)
{
    ul_tdoa_env.stage = UL_TDOA_IDLE;
    ul_tdoa_env.ranging_period = MS_TO_PHY_TIMER_COUNT(uwb_app_config.session_param.ranging_interval);
    ul_tdoa_env.random_window = MS_TO_PHY_TIMER_COUNT(uwb_app_config.session_param.ul_tdoa_random_window);
    ul_tdoa_env.sequence_num = 0;
    ul_tdoa_env.lost_cnt = 0;
    uint32_t seed = 0;
    trng_open();
    trng_get(&seed, 1, NULL);
    trng_close();
    srand(seed);
    LOG_INFO(TRACE_MODULE_APP, "Random seed %u\r\n", seed);
    phy_rx_sts_switch_mode_set(uwb_app_config.ppdu_params.sts_pkt_cfg, STS_NEVER_SWITCH, 0, 0);
    uwbs_configure(PHY_TX | PHY_RX, uwb_app_config.session_param.tx_power_level);
    aoa_param_config();
}
static uint32_t ul_tdoa_tx_offset_get(void)
{
    uint32_t tx_offset_ms = (uint32_t)rand() % uwb_app_config.session_param.ul_tdoa_random_window;
    if (tx_offset_ms < 1)
    {
        tx_offset_ms = 1;
    }
    return MS_TO_PHY_TIMER_COUNT(tx_offset_ms);
}
static void ul_tdoa_pkt_construct(enum OWR_MESSAGE_TYPE_T type, int64_t tx_time)
{
    uint8_t input[160];
    uint8_t input_len = 0;
    /*
     Bits:
     0-2    Frame Type
     3      Long Frame Control
     4-5    Destination Addressing mode
     6-7    Source Addressing mode
     8      PAN ID Present
     9      Security Enabled
     10     Sequence Number Suppression
     11     Frame Pending
     12-13  Frame Version
     14     Ack Request
     15     IE Present
    */
    uint16_t frame_control = (1 << 15) | (1 << 10) | (1 << 9) | (2 << 6) | (1 << 3) | (5 << 0);
    input[input_len++] = frame_control & 0xff;
    input[input_len++] = (frame_control >> 8) & 0xff;
    uint16_t mac_addr = uwbs_local_short_addr_get();
    input[input_len++] = mac_addr & 0xff;
    input[input_len++] = (mac_addr >> 8) & 0xff;
    // Auxiliary Security Header
    uint8_t sec_lvl = 6;
    uint8_t sec_control = (1 << 5) | (uint8_t)(sec_lvl << 0);
    input[input_len++] = sec_control;
    uint32_t phy_sts_index = ul_tdoa_env.sequence_num;
    uint32_t session_id = uwb_app_config.session_id;
    // Header IE - Measurement Report Message Type 1
    uint16_t header_ie = (0x0 << 15) | (0x0 << 7) | (19 << 0);
    uint32_t vendor_oui = 0x5a18ff;
    input[input_len++] = header_ie & 0xff;
    input[input_len++] = (header_ie >> 8) & 0xff;
    input[input_len++] = vendor_oui & 0xff;
    input[input_len++] = (vendor_oui >> 8) & 0xff;
    input[input_len++] = (vendor_oui >> 16) & 0xff;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = 0x08;
    input[input_len++] = session_id & 0xff;
    input[input_len++] = (session_id >> 8) & 0xff;
    input[input_len++] = (session_id >> 16) & 0xff;
    input[input_len++] = (session_id >> 24) & 0xff;
    input[input_len++] = phy_sts_index & 0xff;
    input[input_len++] = (phy_sts_index >> 8) & 0xff;
    input[input_len++] = (phy_sts_index >> 16) & 0xff;
    input[input_len++] = (phy_sts_index >> 24) & 0xff;
    header_ie = (0x7e << 7) | (0 << 0); // HT1 IE
    input[input_len++] = header_ie & 0xff;
    input[input_len++] = (header_ie >> 8) & 0xff;
    // Payload IE
    uint8_t payload_content_len = 16;
    uint16_t payload_ie = (1 << 15) | (0x2 << 11) | (payload_content_len);
    input[input_len++] = payload_ie & 0xff;
    input[input_len++] = (payload_ie >> 8) & 0xff;
    input[input_len++] = vendor_oui & 0xff;
    input[input_len++] = (vendor_oui >> 8) & 0xff;
    input[input_len++] = (vendor_oui >> 16) & 0xff;
    // OWR message type || UWB message ID
    uint8_t uwb_message_id = (uint8_t)(type << 4) | 0x7;
    input[input_len++] = uwb_message_id;
    // Reserved (4) || TX timestamp present (2) || Device ID Present (2)
    uint8_t message_control = (uint8_t)(2 << 2) | 1;
    input[input_len++] = message_control;
    uint32_t frame_number = ul_tdoa_env.sequence_num;
    input[input_len++] = frame_number & 0xff;
    input[input_len++] = (frame_number >> 8) & 0xff;
    input[input_len++] = (frame_number >> 16) & 0xff;
    input[input_len++] = (frame_number >> 24) & 0xff;
    uint8_t *device_id = &uwb_app_config.session_param.ul_tdoa_device_id[1];
    input[input_len++] = device_id[0];
    input[input_len++] = device_id[1];
    input[input_len++] = tx_time & 0xff;
    input[input_len++] = (tx_time >> 8) & 0xff;
    input[input_len++] = (tx_time >> 16) & 0xff;
    input[input_len++] = (tx_time >> 24) & 0xff;
    input[input_len++] = (tx_time >> 32) & 0xff;
    input[input_len++] = (tx_time >> 40) & 0xff;
    input[input_len++] = (tx_time >> 48) & 0xff;
    input[input_len++] = (tx_time >> 56) & 0xff;
    memcpy(&tx_msg[0], &input[0], input_len);
    tx_msg_len = input_len;
}
void ul_tdoa_start(void)
{
    ul_tdoa_env.anchor_point = phy_timer_count_get();
    ul_tdoa_env.tx_offset = ul_tdoa_tx_offset_get();
    enum DEV_ROLE_T role = uwb_app_config.session_param.device_role;
    if (role == DEV_ROLE_UT_SYNC_ANCHOR)
    {
        uint32_t curr_count = phy_timer_count_get();
        uint32_t count = (uint32_t)(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset - curr_count);
        if (count > ul_tdoa_env.random_window)
        {
            count = ul_tdoa_env.random_window;
        }
        if (count > MS_TO_PHY_TIMER_COUNT(2))
        {
            power_on_radio(0, 1);
            ul_tdoa_env.stage = UL_TDOA_LISTEN;
            mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, count - MS_TO_PHY_TIMER_COUNT(2));
            mac_start();
        }
        else
        {
            ul_tdoa_env.stage = UL_TDOA_TX_SYNC;
            phy_timer_target_set(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset - UWB_PERIOD_PREFETCH_TIME, ul_tdoa_timer_callback);
        }
    }
    else if (role == DEV_ROLE_UT_TAG)
    {
        ul_tdoa_env.stage = UL_TDOA_TX_BLINK;
        phy_timer_target_set(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset - UWB_PERIOD_PREFETCH_TIME, ul_tdoa_timer_callback);
    }
    else
    {
        power_on_radio(0, 1);
        ul_tdoa_env.stage = UL_TDOA_LISTEN;
        mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, ul_tdoa_env.random_window);
        mac_start();
    }
    ul_tdoa_env.enable = 1;
    LOG_INFO(TRACE_MODULE_APP, "UL-TDoA start, role %d\r\n", role);
}
void ul_tdoa_stop(void)
{
    ul_tdoa_env.enable = 0;
    LOG_INFO(TRACE_MODULE_APP, "UL-TDoA stop\r\n");
}
static void ul_tdoa_timer_callback(void *dev, uint32_t time)
{
    ul_tdoa_env.sequence_num++;
    // Calculate tx timestamp
    int64_t tx_time = ranging_tx_time(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset + phy_shr_duration());
    enum OWR_MESSAGE_TYPE_T type = (uwb_app_config.session_param.device_role == DEV_ROLE_UT_SYNC_ANCHOR ? OWR_SYNV_UTM : OWR_BLINK_UTM);
    ul_tdoa_pkt_construct(type, tx_time);
    power_on_radio(1, 0);
    mac_tx(EVT_MODE_MAC_ASAP_PHY_FIX, ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset, 0, tx_msg, tx_msg_len);
    mac_start();
}
void ul_tdoa_process(const struct MAC_HW_REPORT_T *ind)
{
    enum DEV_ROLE_T role = uwb_app_config.session_param.device_role;
    if (role == DEV_ROLE_UT_SYNC_ANCHOR)
    {
        if (ul_tdoa_env.stage == UL_TDOA_LISTEN)
        {
            if (ind->err_code == UWB_RX_OK)
            {
                int64_t timestamp = ranging_rx_time(ind);
                ul_tdoa_rx_ind(ind->err_code, ind->pkt_data, ind->pkt_len, timestamp);
            }
        }
        else
        {
            // TX sync done - update next tx offset
            ul_tdoa_env.tx_offset = ul_tdoa_tx_offset_get();
            ul_tdoa_env.anchor_point += ul_tdoa_env.ranging_period;
            LOG_INFO(TRACE_MODULE_APP, "UL-TDoA TX Sync  %u\r\n", ul_tdoa_env.sequence_num);
        }
        uint32_t curr_count = phy_timer_count_get();
        uint32_t count = (uint32_t)(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset - curr_count);
        if (count > ul_tdoa_env.random_window)
        {
            count = ul_tdoa_env.random_window;
        }
        if (count > MS_TO_PHY_TIMER_COUNT(2))
        {
            ul_tdoa_env.stage = UL_TDOA_LISTEN;
            mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, count - MS_TO_PHY_TIMER_COUNT(2));
            mac_start();
        }
        else
        {
            ul_tdoa_env.stage = UL_TDOA_TX_SYNC;
            phy_timer_target_set(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset - UWB_PERIOD_PREFETCH_TIME, ul_tdoa_timer_callback);
            power_off_radio();
        }
    }
    else if (role == DEV_ROLE_UT_TAG)
    {
        // TX blink done - update next tx offset
        ul_tdoa_env.tx_offset = ul_tdoa_tx_offset_get();
        ul_tdoa_env.anchor_point += ul_tdoa_env.ranging_period;
        phy_timer_target_set(ul_tdoa_env.anchor_point + ul_tdoa_env.tx_offset - UWB_PERIOD_PREFETCH_TIME, ul_tdoa_timer_callback);
        power_off_radio();
        LOG_INFO(TRACE_MODULE_APP, "UL-TDoA TX Blink  %u\r\n", ul_tdoa_env.sequence_num);
    }
    else
    {
        if (ind->err_code == UWB_RX_OK)
        {
            int64_t timestamp = ranging_rx_time(ind);
            ul_tdoa_rx_ind(ind->err_code, ind->pkt_data, ind->pkt_len, timestamp);
        }
        mac_rx(EVT_MODE_MAC_PHY_ASAP, 0, ul_tdoa_env.random_window);
        mac_start();
    }
}
void ul_tdoa_rx_ind(uint16_t status, const uint8_t *data, uint16_t len, int64_t timestamp)
{
    struct UL_TDOA_RX_IND_T *ind;
    if ((ind = WsfMsgAlloc(sizeof(struct UL_TDOA_RX_IND_T) + len)) != NULL)
    {
        ind->hdr.event = UL_TDOA_RX_IND_MSG;
        ind->status = status;
        ind->rx_len = len;
        ind->rx_timestamp = timestamp;
        if (data != NULL)
        {
            memcpy(ind->rx_data, data, len);
        }
        // Send the message
        WsfMsgSend(ul_tdoa_cb.handle_id, ind);
    }
}
static void ul_tdoa_tx_process(struct MAC_HW_REPORT_T *tx_report)
{
    ul_tdoa_process(tx_report);
}
static void ul_tdoa_rx_process(struct MAC_HW_REPORT_T *rx_report)
{
    ul_tdoa_process(rx_report);
}