blob: 9c3aec5ff82d0769036fe04dce06513187ed9c91 [file] [log] [blame]
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <bluetooth/hci.h>
#include "util/util.h"
#include "util/memq.h"
#include "hal/cpu.h"
#include "hal/radio_df.h"
#include "pdu.h"
#include "lll.h"
#include "lll_df.h"
#include "lll_df_types.h"
#include "lll_df_internal.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_CTLR_DF_DEBUG_ENABLE)
#define LOG_MODULE_NAME bt_ctlr_lll_df
#include "common/log.h"
#include <soc.h>
#include "hal/debug.h"
/* @brief Function performs common steps for initialization and reset
* of Direction Finding LLL module.
*
* @return Zero in case of success, other value in case of failure.
*/
static int init_reset(void);
/* @brief Function performs Direction Finding initialization
*
* @return Zero in case of success, other value in case of failure.
*/
int lll_df_init(void)
{
#if defined(CONFIG_BT_CTLR_DF_INIT_ANT_SEL_GPIOS)
radio_df_ant_switching_gpios_cfg();
#endif /* CONFIG_BT_CTLR_DF_INIT_ANT_SEL_GPIOS */
return init_reset();
}
/* @brief Function performs Direction Finding reset
*
* @return Zero in case of success, other value in case of failure.
*/
int lll_df_reset(void)
{
return init_reset();
}
/* @brief Function provides number of available antennas.
*
* The number of antenna is hardware defined and it is provided via devicetree.
*
* @return Number of available antennas.
*/
uint8_t lll_df_ant_num_get(void)
{
return radio_df_ant_num_get();
}
/* @brief Function initializes transmission of Constant Tone Extension.
*
* @param[in] type Type of CTE: AoA, AoD 1us, AoD 2us
* @param[in] length Duration of CTE in 8us units
* @param[in] ant_num Number of antennas in switch pattern
* @param[in] ant_ids Antenna identifiers that create switch pattern.
*
* @Note Pay attention that first two antenna identifiers in a switch
* pattern has special purpose. First one is used in guard period, second
* in reference period. Actual switching is processed from third antenna.
*
* In case of AoA mode ant_num and ant_ids parameters are not used.
*/
void lll_df_conf_cte_tx_enable(uint8_t type, uint8_t length,
uint8_t ant_num, uint8_t *ant_ids)
{
if (type == BT_HCI_LE_AOA_CTE) {
radio_df_mode_set_aoa();
radio_df_cte_tx_aoa_set(length);
}
#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) || \
defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
else {
radio_df_mode_set_aod();
if (type == BT_HCI_LE_AOD_CTE_1US) {
radio_df_cte_tx_aod_2us_set(length);
} else {
radio_df_cte_tx_aod_4us_set(length);
}
radio_df_ant_switching_pin_sel_cfg();
radio_df_ant_switch_pattern_clear();
radio_df_ant_switch_pattern_set(ant_ids, ant_num);
}
#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX || CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */
}
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
struct lll_df_sync_cfg *lll_df_sync_cfg_alloc(struct lll_df_sync *df_cfg,
uint8_t *idx)
{
uint8_t first, last;
first = df_cfg->first;
last = df_cfg->last;
if (first == last) {
last++;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0U;
}
} else {
uint8_t first_latest;
df_cfg->last = first;
cpu_dmb();
first_latest = df_cfg->first;
if (first_latest != first) {
last++;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0U;
}
}
}
*idx = last;
return &df_cfg->cfg[last];
}
struct lll_df_sync_cfg *lll_df_sync_cfg_latest_get(struct lll_df_sync *df_cfg,
uint8_t *is_modified)
{
uint8_t first;
first = df_cfg->first;
if (first != df_cfg->last) {
uint8_t cfg_idx;
cfg_idx = first;
first += 1U;
if (first == DOUBLE_BUFFER_SIZE) {
first = 0U;
}
df_cfg->first = first;
if (is_modified) {
*is_modified = 1U;
}
df_cfg->cfg[cfg_idx].is_enabled = 0U; /* mark as disabled - not used anymore */
}
return &df_cfg->cfg[first];
}
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
void lll_df_conf_cte_tx_disable(void)
{
radio_df_reset();
}
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
/* @brief Function initializes reception of Constant Tone Extension.
*
* @param[in] slot_duration Switching and sampling slots duration (1us or 2us).
* @param[in] ant_num Number of antennas in switch pattern.
* @param[in] ant_ids Antenna identifiers that create switch pattern.
*
* In case of AoA mode ant_num and ant_ids parameters are not used.
*/
void lll_df_conf_cte_rx_enable(uint8_t slot_duration, uint8_t ant_num,
uint8_t *ant_ids)
{
struct node_rx_iq_report *node_rx;
/* ToDo change to appropriate HCI constant */
#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_1US)
if (slot_duration == 0x1) {
radio_df_cte_rx_2us_switching();
} else
#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_1US */
{
radio_df_cte_rx_4us_switching();
}
#if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
radio_df_ant_switching_pin_sel_cfg();
radio_df_ant_switch_pattern_clear();
radio_df_ant_switch_pattern_set(ant_ids, ant_num);
#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */
node_rx = ull_df_iq_report_alloc_peek(1);
LL_ASSERT(node_rx);
radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT);
}
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
static int init_reset(void)
{
return 0;
}