/***************************************************************************
 *
 * Copyright 2015-2019 BES.
 * All rights reserved. All unpublished rights reserved.
 *
 * No part of this work may be used or reproduced in any form or by any
 * means, or stored in a database or retrieval system, without prior written
 * permission of BES.
 *
 * Use of this work is governed by a license granted by BES.
 * This work contains confidential and proprietary information of
 * BES. which is protected by copyright, trade secret,
 * trademark and other intellectual property rights.
 *
 ****************************************************************************/
#include "bt_drv.h"
#include "bt_drv_2300p_internal.h"
#include "bt_drv_interface.h"
#include "bt_drv_internal.h"
#include "bt_drv_reg_op.h"
#include "hal_chipid.h"
#include "hal_i2c.h"
#include "hal_timer.h"
#include "hal_uart.h"
#include "plat_types.h"
#include "tgt_hardware.h"
#include <string.h>
// typedef void (*btdrv_config_func_t)(uint8_t parlen, uint8_t *param);

extern void btdrv_send_cmd(uint16_t opcode, uint8_t cmdlen,
                           const uint8_t *param);
extern void btdrv_write_memory(uint8_t wr_type, uint32_t address,
                               const uint8_t *value, uint8_t length);

typedef struct {
  //    btdrv_config_func_t    func;
  uint8_t is_act;
  uint16_t opcode;
  uint8_t parlen;
  const uint8_t *param;

} BTDRV_CFG_TBL_STRUCT;

#define BTDRV_CONFIG_ACTIVE 1
#define BTDRV_CONFIG_INACTIVE 0
#define BTDRV_INVALID_TRACE_LEVEL 0xFF
/*
[0][0] = 63, [0][1] = 0,[0][2] = (-80),           472d
[1][0] = 51, [2][1] = 0,[2][2] = (-80),          472b
[2][0] = 42, [4][1] = 0,[4][2] = (-75),           4722
[3][0] = 36, [6][1] = 0,[6][2] = (-55),           c712
[4][0] = 30, [8][1] = 0,[8][2] = (-40),           c802
[5][0] = 21,[10][1] = 0,[10][2] = 0x7f,         c102
[6][0] = 12,[11][1] = 0,[11][2] = 0x7f,       c142
[7][0] = 3,[13][1] = 0,[13][2] = 0x7f,        c1c2
[8][0] = -3,[14][1] = 0,[14][2] = 0x7f};      c0c2
*/
static uint8_t g_controller_trace_level = BTDRV_INVALID_TRACE_LEVEL;
static bool g_lmp_trace_enable = false;
const int8_t btdrv_rf_env_2300p[] = {
    0x01, 0x00, // rf api
    0x01,       // rf env
    185,        // rf length
    0x2,        // txpwr_max
#ifdef __HW_AGC__
    -1,   // high
    -2,   // low
    -100, // interf
#else
    -1,   /// rssi high thr
    -2,   // rssi low thr
    -100, // rssi interf thr
#endif
    0xf,       // rssi interf gain thr
    2,         // wakeup delay
    0xe, 0,    // skew
    0xe8, 0x3, // ble agc inv thr
#ifdef __HW_AGC__
    0x1, // hw_sw_agc_flag
#else
    0x0,  //
#endif
    0xff, // sw gain set
    0xff, // sw gain set
    -70,  // bt_inq_page_iscan_pscan_dbm
    0x7f, // ble_scan_adv_dbm
    1,    // sw gain reset factor
    1,    // bt sw gain cntl enable
    0,    // ble sw gain cntl en
    1,    // bt interfere  detector en
    0,    // ble interfere detector en

    -21, -27, -19, -18, -24, -13, -15, -21, -10, -12, -18, -10, -9, -15, -10,
    -6, -12, -10, -3, -9, -10, 0, -6, 0, 0x7f, -3, 0x7f, 0x7f, 0, 0x7f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, 0x7f, // rx hwgain tbl ptr

    // zhangzhd agc config use default 1216
    50, 0, -80, 42, 0, -80, 38, 0, -80, 32, 0, -80, 26, 0, -80, 21, 0, -80, 15,
    0, -80, 9, 0, -80,
    // zhangzhd agc config end

    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, // rx gain tbl ptr
    // zhangzhd agc config use default 1216
    -80, -73, -75, -68, -70, -63, -65, -58, -60, -53, -55, -48, -50, -15,
    // zhangzhd agc config end

    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, // rx gain ths tbl ptr

    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 2, 0, 2, 0x7f, 0x7f, 0x7f,
    0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, // flpha filter factor ptr
    -23, -20, -17, -14, -11, -8, -5, -2, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
    0x7f, // tx pw onv tbl ptr
};

const int8_t btdrv_afh_env[] = {
    0x02, 0x00,          // afh env
    0x00,                // ignore
    33,                  // length
    5,                   // nb_reass_chnl
    10,                  // win_len
    -70,                 // rf_rssi_interf_thr
    10,                  // per_thres_bad
    20,                  // reass_int
    20,                  // n_min
    20,                  // afh_rep_intv_max
    96,                  // ths_min
    2,                   // chnl_assess_report_style
    15,                  // chnl_assess_diff_thres
    60,                  // chnl_assess_interfere_per_thres_bad
    9,                   // chnl_assess_stat_cnt_max
    -9,                  // chnl_assess_stat_cnt_min
    1,    2,    3, 2, 1, // chnl_assess_stat_cnt_inc_mask[5]
    1,    2,    3, 2, 1, // chnl_assess_stat_cnt_dec_mask
    0xd0, 0x7,           // chnl_assess_timer
    -48,                 // chnl_assess_min_rssi
    0x64, 0,             // chnl_assess_nb_pkt
    0x32, 0,             // chnl_assess_nb_bad_pkt
    6,                   // chnl_reassess_cnt_val
    0x3c, 0,             // chnl_assess_interfere_per_thres_bad
};

const uint8_t lpclk_drift_jitter[] = {
    0xfa, 0x00, //  drift  250ppm
    0x0a, 0x00  // jitter  +-10us

};

const uint8_t wakeup_timing[] = {
    0xe8, 0x3, // exernal_wakeup_time 600us
    0xe8, 0x3, // oscillater_wakeup_time  600us
    0xe8, 0x3, // radio_wakeup_time  600us
               // 0xa0,0xf,    //wakeup_delay_time
};

uint8_t sleep_param[] = {
    1,             // sleep_en;
    0,             // exwakeup_en;
    0xc8, 0,       //  lpo_calib_interval;   lpo calibration interval
    0x32, 0, 0, 0, // lpo_calib_time;  lpo count lpc times
};

uint8_t unsleep_param[] = {
    0,             // sleep_en;
    0,             // exwakeup_en;
    0xc8, 0,       //  lpo_calib_interval;   lpo calibration interval
    0x32, 0, 0, 0, // lpo_calib_time;  lpo count lpc times
};

static const uint32_t me_init_param[][2] = {
    {0xffffffff, 0xffffffff},
};

const uint16_t me_bt_default_page_timeout = 0x2000;

const uint8_t sync_config[] = {
    1, 1, // sco path config   0:hci  1:pcm
    0,    // sync use max buff length   0:sync data length= packet length 1:sync
          // data length = host sync buff len
    0,    // cvsd bypass     0:cvsd2pcm   1:cvsd transparent
};

// pcm general ctrl
#define PCM_PCMEN_POS 15
#define PCM_LOOPBCK_POS 14
#define PCM_MIXERDSBPOL_POS 11
#define PCM_MIXERMODE_POS 10
#define PCM_STUTTERDSBPOL_POS 9
#define PCM_STUTTERMODE_POS 8
#define PCM_CHSEL_POS 6
#define PCM_MSTSLV_POS 5
#define PCM_PCMIRQEN_POS 4
#define PCM_DATASRC_POS 0

// pcm phy ctrl
#define PCM_LRCHPOL_POS 15
#define PCM_CLKINV_POS 14
#define PCM_IOM_PCM_POS 13
#define PCM_BUSSPEED_LSB 10
#define PCM_SLOTEN_MASK ((uint32_t)0x00000380)
#define PCM_SLOTEN_LSB 7
#define PCM_WORDSIZE_MASK ((uint32_t)0x00000060)
#define PCM_WORDSIZE_LSB 5
#define PCM_DOUTCFG_MASK ((uint32_t)0x00000018)
#define PCM_DOUTCFG_LSB 3
#define PCM_FSYNCSHP_MASK ((uint32_t)0x00000007)
#define PCM_FSYNCSHP_LSB 0

/// Enumeration of PCM status
enum PCM_STAT { PCM_DISABLE = 0, PCM_ENABLE };

/// Enumeration of PCM channel selection
enum PCM_CHANNEL { PCM_CH_0 = 0, PCM_CH_1 };

/// Enumeration of PCM role
enum PCM_MSTSLV { PCM_SLAVE = 0, PCM_MASTER };

/// Enumeration of PCM data source
enum PCM_SRC { PCM_SRC_DPV = 0, PCM_SRC_REG };

/// Enumeration of PCM left/right channel selection versus frame sync polarity
enum PCM_LR_CH_POL { PCM_LR_CH_POL_RIGHT_LEFT = 0, PCM_LR_CH_POL_LEFT_RIGHT };

/// Enumeration of PCM clock inversion
enum PCM_CLK_INV { PCM_CLK_RISING_EDGE = 0, PCM_CLK_FALLING_EDGE };

/// Enumeration of PCM mode selection
enum PCM_MODE { PCM_MODE_PCM = 0, PCM_MODE_IOM };

/// Enumeration of PCM bus speed
enum PCM_BUS_SPEED {
  PCM_BUS_SPEED_128k = 0,
  PCM_BUS_SPEED_256k,
  PCM_BUS_SPEED_512k,
  PCM_BUS_SPEED_1024k,
  PCM_BUS_SPEED_2048k
};

/// Enumeration of PCM slot enable
enum PCM_SLOT {
  PCM_SLOT_NONE = 0,
  PCM_SLOT_0,
  PCM_SLOT_0_1,
  PCM_SLOT_0_2,
  PCM_SLOT_0_3
};

/// Enumeration of PCM word size
enum PCM_WORD_SIZE { PCM_8_BITS = 0, PCM_13_BITS, PCM_14_BITS, PCM_16_BITS };

/// Enumeration of PCM DOUT pad configuration
enum PCM_DOUT_CFG { PCM_OPEN_DRAIN = 0, PCM_PUSH_PULL_HZ, PCM_PUSH_PULL_0 };

/// Enumeration of PCM FSYNC physical shape
enum PCM_FSYNC {
  PCM_FSYNC_LF = 0,
  PCM_FSYNC_FR,
  PCM_FSYNC_FF,
  PCM_FSYNC_LONG,
  PCM_FSYNC_LONG_16
};

const uint32_t pcm_setting[] = {
    // pcm_general_ctrl
    (PCM_DISABLE << PCM_PCMEN_POS) |       // enable auto
        (PCM_DISABLE << PCM_LOOPBCK_POS) | // LOOPBACK test
        (PCM_DISABLE << PCM_MIXERDSBPOL_POS) |
        (PCM_DISABLE << PCM_MIXERMODE_POS) |
        (PCM_DISABLE << PCM_STUTTERDSBPOL_POS) |
        (PCM_DISABLE << PCM_STUTTERMODE_POS) | (PCM_CH_0 << PCM_CHSEL_POS) |
        (PCM_MASTER << PCM_MSTSLV_POS) | // BT clock
        (PCM_DISABLE << PCM_PCMIRQEN_POS) | (PCM_SRC_DPV << PCM_DATASRC_POS),

    // pcm_phy_ctrl
    (PCM_LR_CH_POL_RIGHT_LEFT << PCM_LRCHPOL_POS) |
        (PCM_CLK_FALLING_EDGE << PCM_CLKINV_POS) |
        (PCM_MODE_PCM << PCM_IOM_PCM_POS) |
        (PCM_BUS_SPEED_2048k
         << PCM_BUSSPEED_LSB) | // 8k sample rate; 2048k = slot_num *
                                // sample_rate * bit= 16 * 8k * 16
        (PCM_SLOT_0_1 << PCM_SLOTEN_LSB) |
        (PCM_16_BITS << PCM_WORDSIZE_LSB) |
        (PCM_PUSH_PULL_0 << PCM_DOUTCFG_LSB) |
        (PCM_FSYNC_LF << PCM_FSYNCSHP_LSB),
};

#if 1
const uint8_t local_feature[] = {
#if defined(__3M_PACK__)
    0xBF, 0xeE, 0xCD, 0xFe, 0xdb,
    0xFd, 0x7b, 0x87
#else
    0xBF, 0xeE, 0xCD, 0xFa, 0xdb,
    0xbd, 0x7b, 0x87

// 0xBF,0xFE,0xCD,0xFa,0xDB,0xFd,0x73,0x87   // disable simple pairing
#endif
};

#else
// disable simple pairing
uint8_t local_feature[] = {0xBF, 0xFE, 0xCD, 0xFE, 0xDB, 0xFd, 0x73, 0x87};
#endif
const uint8_t local_ex_feature_page1[] = {
    1,                      // page
    0, 0, 0, 0, 0, 0, 0, 0, // page 1 feature
};

const uint8_t local_ex_feature_page2[] = {
    2,                                              // page
    0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // page 2 feature
};

const uint8_t bt_rf_timing[] = {
    0xE,  // tx delay
    0x13, // rx delay
    0x42, // rx pwrup
    0x0f, /// tx down
    0x56, // tx pwerup

};

const uint8_t ble_rf_timing[] = {
    0xC,  // tx delay   tx after rx delay
    0x2C, // win count   rx window count
    0xe,  /// ble rtrip delay
    0x42, /// ble rx pwrup
    0x7,  /// ble tx pwerdown
    0x40, /// ble tx pwerup
};

const uint8_t ble_rl_size[] = {
    10, // rl size
};

uint8_t bt_setting_2300p[97] = {
    0x00,       // clk_off_force_even
    0x01,       // msbc_pcmdout_zero_flag
    0x04,       // ld_sco_switch_timeout
    0x01,       // stop_latency2
    0x01,       // force_max_slot
    0xc8, 0x00, // send_connect_info_to
    0x20, 0x03, // sco_to_threshold
    0x40, 0x06, // acl_switch_to_threshold
    0x3a, 0x00, // sync_win_size
    0x01,       // polling_rxseqn_mode
#ifdef __BT_ONE_BRING_TWO__
    0x01, // two_slave_sched_en
#else
    0x00, // two_slave_sched_en
#endif
    0xff,                   // music_playing_link
    0x04,                   // wesco_nego = 2;
    0x17, 0x11, 0x00, 0x00, // two_slave_extra_duration_add (7*625);
    0x01,                   // ble_adv_ignore_interval
    0x04,                   // slot_num_diff
    0x01,                   // csb_tx_complete_event_enable
    0x04,                   // csb_afh_update_period
    0x00,                   // csb_rx_fixed_len_enable
    0x01,                   // force_max_slot_acc
    0x00,                   // force_5_slot;
#ifdef BT_CONTROLER_DEBUG_TRACE
    0x03, // dbg_trace_level
#else
    0x00,
#endif
    0x00,       // bd_addr_switch
    0x00,       // force_rx_error
    0x08,       // data_tx_adjust
    0x02,       // ble txpower need modify ble tx idx @ bt_drv_config.c;
    0x50,       // sco_margin
    0x78,       // acl_margin
    0x01,       // pca_disable_in_nosync
    0x01,       // master_2_poll
    0x3a,       // sync2_add_win
    0x5e,       // no_sync_add_win
    0x09,       // rwbt_sw_version_major
    0x03, 0x00, // rwbt_sw_version_minor
    0x21, 0x00, // rwbt_sw_version_build

    0x01, // rwbt_sw_version_sub_build
    0x00, // public_key_check;
    0x00, // sco_txbuff_en;
    0x3f, // role_switch_packet_br;
    0x2b, // role_switch_packet_edr;
    0x00, // dual_slave_tws_en;
    0x07, // dual_slave_slot_add;
    0x00, // master_continue_tx_en;

    0x20, 0x03, // get_rssi_to_threshold;
    0x05,       // rssi_get_times;
    0x00,       // ptt_check;
    0x0c,       // protect_sniff_slot;
    0x00,       // power_control_type;
#ifdef TX_RX_PCM_MASK
    1, // sco_buff_copy
#else
    0,                      // sco_buff_copy
#endif
    0x32, 0x00, // acl_interv_in_snoop_mode;
    0x78, 0x00, // acl_interv_in_snoop_sco_mode;

    0x06, // acl_slot_in_snoop_mode;
    0x01, // calculate_en;
    0x00, // check_sniff_en;
    0x01, // sco_avoid_ble_en;
    0x01, // check_ble_en;
    0x01, // ble_slot;
    0x00, // same_link_slave_extra;
    0x00, // other_link_slave_extra;

    0x00,                   // master_extra;
    0x00,                   // ble_extra;
    0x00,                   // sco_extra;
    0x00,                   // sniff_extra;
    0x00, 0x00, 0x00, 0x00, // same_link_duration;
    0x00, 0x00, 0x00, 0x00, // other_link_duration;

    0x06,       // dual_slave;
    0x0a,       // clk_check_threshold;
    0x90, 0x01, // target_clk_add;
    0x01,       // close_check_sco_to;
    // 0x00,
    // 0x00,                //chip tports_level (wrong) use
    // btdrv_2300p_set_tports_level() 0x00,
    0x01, //(tports_level)//chip read close_loopbacken_flag
    0x01, // chip read based_clk_select
    0x01, // chip read check_role_switch
    0x00, // chip read rsw_end_prority
    0x00, // chip read ecc_enable
    0x00, // padding to 97-byte
    0x00, // padding to 97-byte
    0x00, // padding to 97-byte
    0x00, // padding to 97-byte
};

//#define ACCEPT_NEW_MOBILE_EN

uint8_t bt_setting_2300p_t2[104] = {
    0x00,       // clk_off_force_even
    0x01,       // msbc_pcmdout_zero_flag
    0x04,       // ld_sco_switch_timeout
    0x00,       // stop_latency2
    0x01,       // force_max_slot
    0xc8, 0x00, // send_connect_info_to
    0x20, 0x03, // sco_to_threshold
    0x40, 0x06, // acl_switch_to_threshold
    0x3a, 0x00, // sync_win_size
    0x01,       // polling_rxseqn_mode
#ifdef __BT_ONE_BRING_TWO__
    0x01, // two_slave_sched_en
#else
    0x00,                   // two_slave_sched_en
#endif
    0xff,                   // music_playing_link
    0x04,                   // wesco_nego = 2;
    0x17, 0x11, 0x00, 0x00, // two_slave_extra_duration_add (7*625);
    0x01,                   // ble_adv_ignore_interval
    0x04,                   // slot_num_diff
    0x01,                   // csb_tx_complete_event_enable
    0x04,                   // csb_afh_update_period
    0x00,                   // csb_rx_fixed_len_enable
    0x01,                   // force_max_slot_acc
    0x00,                   // force_5_slot;
    0x00,                   // dbg_trace_level
    0x00,                   // bd_addr_switch
    0x00,                   // force_rx_error
    0x08,                   // data_tx_adjust
    0x02,       // ble txpower need modify ble tx idx @ bt_drv_config.c;
    0x50,       // sco_margin
    0x78,       // acl_margin
    0x01,       // pca_disable_in_nosync
    0x01,       // master_2_poll
    0x3a,       // sync2_add_win
    0x5e,       // no_sync_add_win
    0x09,       // rwbt_sw_version_major
    0x03, 0x00, // rwbt_sw_version_minor
    0x21, 0x00, // rwbt_sw_version_build

    0x01, // rwbt_sw_version_sub_build
    0x00, // public_key_check;
    0x00, // sco_txbuff_en;
    0x3f, // role_switch_packet_br;
    0x2b, // role_switch_packet_edr;
    0x00, // dual_slave_tws_en;
    0x07, // dual_slave_slot_add;
    0x00, // master_continue_tx_en;

    0x20, 0x03, // get_rssi_to_threshold;
    0x05,       // rssi_get_times;
    0x00,       // ptt_check;
    0x0c,       // protect_sniff_slot;
    0x01,       // power_control_type;
#ifdef TX_RX_PCM_MASK
    0x01, // sco_buff_copy
#else
    0x00,                   // sco_buff_copy
#endif
    0x32, 0x00, // acl_interv_in_snoop_mode;
    0x48, 0x00, // acl_interv_in_snoop_sco_mode;

    0x06, // acl_slot_in_snoop_mode;
    0x01, // calculate_en;
    0x00, // check_sniff_en;
    0x01, // sco_avoid_ble_en;
    0x01, // check_ble_en;
    0x01, // ble_slot;
    0x00, // same_link_slave_extra;
    0x00, // other_link_slave_extra;

    0x00, // master_extra;
    0x00, // ble_extra;
    0x00, // sco_extra;
    0x00, // sniff_extra;
#ifdef __FORCE_SCO_MAX_RETX__
    0x02, 0x00, 0x00, 0x00, // same_link_duration;
#else
    0x00, 0x00, 0x00, 0x00, // same_link_duration;
#endif
    0x00, 0x00, 0x00, 0x00, // other_link_duration;

    0x06,       // dual_slave;
    0x14,       // clk_check_threshold;
    0x90, 0x01, // target_clk_add;
    0x01,       // close_check_sco_to;
    0x00, 0x00, //(tports_level)
    0x01,       // close_loopbacken_flag
    0x1e,       // seq_error_num
    0x01,       // check_role_switch
    0x01,       // rsw_end_prority
#ifdef __FASTACK_ECC_ENABLE__
    0x01, // ecc_enable
#else
    0x00,                   // ecc_enable
#endif
    0x01, // sw_seq_filter_en
    0x01, // page_pagescan_coex_en
#ifdef ACCEPT_NEW_MOBILE_EN
    0x01, // accept_new_mobile_en
#else
    0x00,
#endif
    0x64,       // reserve_slot_for_send_profile
    0x0e,       // magic_cal_bitoff
    0x00,       // sco_role_switch_mode
    0x00,       // address_reset
    0xa6, 0x0e, // adv_duration
};

uint8_t bt_setting_ext1_2300p_t3[25] = {
    0x00, 0x01, // stop_notif_bit_off_thr
    0x32, 0x00, // bit_off_diff
    0x00,       // bt_wlan_onoff
    0x12,       // tws_link_in_sco_prio
    0x01,       // tws_link_rx_traficc
    0x00,       // tws_link_ignore_1_sco;
    0x08,       // default_tpoll
    0x00,       // send_profile_via_ble
    0x0a,       // swagc_thd
    0x98,       // swagc_count
    0x14,       // max_drift_limit
    0x00,       // sync2_sco_cal_enable
#ifdef IBRT
    0x00, // accep_remote_bt_roleswitch
#else
    0x01,
#endif
    0x01,       // hci_auto_accept_tws_link_en
    0x00,       // enable_assert
    0x00,       // reserved
    0xc8, 0x00, // hci_timeout_sleep
    0x50,       // link_no_snyc_thd
    0xa6,       // link_no_sync_rssi(-90dBm)
    0x64, 0x00, // link_no_sync_timeout
    0x01,       // ibrt_role_switch_check_sco
};

bool btdrv_get_accept_new_mobile_enable(void) {
  bool ret = false;
  if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_1) {
    BT_DRV_TRACE(1, "BT_DRV_CONFIG:accept_new_mobile enable=%d",
                 bt_setting_2300p_t2[97]);
    ret = bt_setting_2300p_t2[97];
  }
  return ret;
}

bool btdrv_get_page_pscan_coex_enable(void) {
  bool ret = false;
  if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_1) {
    BT_DRV_TRACE(1, "BT_DRV_CONFIG:page_pscan_coex enable=%d",
                 bt_setting_2300p_t2[96]);
    ret = bt_setting_2300p_t2[96];
  }
  return ret;
}

const uint8_t bt_edr_thr[] = {
    30,   0,    60,   0,    5,    0,    60,   0,    0,    1,    30,   0,
    60,   0,    5,    0,    60,   0,    1,    1,    30,   0,    60,   0,
    5,    0,    60,   0,    1,    1,    0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};

const uint8_t bt_edr_algo[] = {
    0,    0,    1,    8,    0,    3,    16,   0,    0,    0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};

const uint8_t bt_rssi_thr[] = {
    -1,   // high
    -2,   // low
    -100, // interf
};

const uint8_t ble_dle_dft_value[] = {
    0xfb, 0x00, /// tx octets
    0x48, 0x08, /// tx time
    0xfb, 0x00, /// rx octets
    0x48, 0x08, /// rx time
};

uint8_t bt_lmp_record[] = {
    0, // en
    0, // only opcode
};

static BTDRV_CFG_TBL_STRUCT btdrv_cfg_tbl[] = {
    {BTDRV_CONFIG_INACTIVE, HCI_DBG_LMP_MESSAGE_RECORD_CMD_OPCODE,
     sizeof(bt_lmp_record), (uint8_t *)&bt_lmp_record},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_LOCAL_FEATURE_CMD_OPCODE,
     sizeof(local_feature), local_feature},
    {BTDRV_CONFIG_INACTIVE, HCI_DBG_SET_BT_SETTING_CMD_OPCODE,
     sizeof(bt_setting_2300p), bt_setting_2300p},
    {BTDRV_CONFIG_INACTIVE, HCI_DBG_SET_BT_SETTING_CMD_OPCODE,
     sizeof(bt_setting_2300p_t2), bt_setting_2300p_t2},
    {BTDRV_CONFIG_INACTIVE, HCI_DBG_SET_BT_SETTING_EXT1_CMD_OPCODE,
     sizeof(bt_setting_ext1_2300p_t3), bt_setting_ext1_2300p_t3},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_SLEEP_SETTING_CMD_OPCODE,
     sizeof(sleep_param), sleep_param},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_CUSTOM_PARAM_CMD_OPCODE, 189,
     (uint8_t *)&btdrv_rf_env_2300p},
//{BTDRV_CONFIG_ACTIVE,HCI_DBG_SET_CUSTOM_PARAM_CMD_OPCODE,sizeof(btdrv_afh_env),(uint8_t
//*)&btdrv_afh_env},
// {BTDRV_CONFIG_INACTIVE,HCI_DBG_SET_LPCLK_DRIFT_JITTER_CMD_OPCODE,sizeof(lpclk_drift_jitter),(uint8_t
// *)&lpclk_drift_jitter},
// {BTDRV_CONFIG_ACTIVE,HCI_DBG_SET_WAKEUP_TIME_CMD_OPCODE,sizeof(wakeup_timing),(uint8_t
// *)&wakeup_timing},
#ifdef _SCO_BTPCM_CHANNEL_
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_SYNC_CONFIG_CMD_OPCODE,
     sizeof(sync_config), (uint8_t *)&sync_config},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_PCM_SETTING_CMD_OPCODE,
     sizeof(pcm_setting), (uint8_t *)&pcm_setting},
#endif
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_RSSI_THRHLD_CMD_OPCODE,
     sizeof(bt_rssi_thr), (uint8_t *)&bt_rssi_thr},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_LOCAL_EX_FEATURE_CMD_OPCODE,
     sizeof(local_ex_feature_page2), (uint8_t *)&local_ex_feature_page2},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_BT_RF_TIMING_CMD_OPCODE,
     sizeof(bt_rf_timing), (uint8_t *)&bt_rf_timing},
    {BTDRV_CONFIG_ACTIVE, HCI_DBG_SET_BLE_RF_TIMING_CMD_OPCODE,
     sizeof(ble_rf_timing), (uint8_t *)&ble_rf_timing},
};

const static POSSIBLY_UNUSED BTDRV_CFG_TBL_STRUCT btdrv_cfg_tbl_2[] = {

};

const static POSSIBLY_UNUSED uint32_t mem_config_2300p[][2] = {

};

void bt_drv_digital_config_for_ble_adv(bool en) {
#ifdef __HW_AGC__
  btdrv_hw_agc_stop_mode(BT_SYNCMODE_REQ_USER_BLE, en);
#endif
}

void btdrv_digital_config_init_2300p_t2(void) {
  // common
  BTDIGITAL_REG(0xd0350370) |= (1 << 29);  // lowpass flt enable
  BTDIGITAL_REG(0xd0330038) |= (1 << 11);  // sel 26m sys
  BTDIGITAL_REG(0xd0330038) &= 0xffffff3f; // sel 26m sys
  BTDIGITAL_REG(0xd03300f0) &= ~0x1;       // sel 26m sys

  BTDIGITAL_REG(0xd0350398) = 0x6e4ef79c;
  BTDIGITAL_REG(0xd03503a8) = 0x15A64E88;

  // IBRT
  BTDIGITAL_REG(0xd0220464) &= 0xdfffffff; // fast ack 2M mode dis

#ifdef __FASTACK_ECC_ENABLE__
  BTDIGITAL_REG(0xd0220468) = 0x04401914; // fast ack timings & fastlock en
#else
  BTDIGITAL_REG(0xd0220468) = 0x10423528; // fast ack timings
#endif //__FASTACK_ECC_ENABLE__

#ifdef __FA_RX_GAIN_CTRL__
  BTDIGITAL_REG(0xd0220080) &= 0xff00ffff;
  BTDIGITAL_REG(0xd0220080) |= 0x00770000; // trx pwrup/dn
  BTDIGITAL_REG(0xd02201e8) |= 1;          // second rf spi en
  BTDIGITAL_REG(0xd0220480) = (BTDIGITAL_REG(0xd0220480) & (~0xff)) | 0xbf;
  BTDIGITAL_REG(0xd0220484) =
      (BTDIGITAL_REG(0xd0220484) & (~0xffff)) |
      0x9403; // lxd 20191102 fixed ecc receive gain to 1 level
#endif
#ifdef __CLK_GATE_DISABLE__
  BTDIGITAL_REG(0xD0330024) &= (~0x00020);
  BTDIGITAL_REG(0xD0330024) |= 0x40000;
  BTDIGITAL_REG(0xD0330038) |= 0x200000;
#endif
}

void btdrv_digital_config_init_2300p_t1(void) {
#ifdef BT_RF_OLD_CORR_MODE
  BTDIGITAL_REG(0xD03503A0) &= (~0x01); // clear bit 0 avoid slave lost data
#else
  BTDIGITAL_REG(0xD03503A0) |= (0x01);
#endif
  BTDIGITAL_REG(0x40000074) = 0x00003100;
  BTDIGITAL_REG(0x400000F0) = 0xFFFF0002; // open slot en

  BTDIGITAL_REG(0xd0350240) = 0x0001a407;
  BTDIGITAL_REG(0xd03502c8) = 0x00000080; // for old ramp
  BTDIGITAL_REG(0xd03502cc) = 0x00000015; // for old ramp

#ifdef __HW_AGC__
  BTDIGITAL_REG(0xd0350208) = 0x7fffffff;
  btdrv_delay(10);
  BTDIGITAL_REG(0xd0350228) = 0x7f7fffff;
  BTDIGITAL_REG(0xd03300f0) = 0xffff0008; // hwagc config
  BTDIGITAL_REG(0xd03503b8) = 0x08000d80; // hwagc config
#endif

  BTDIGITAL_REG(0xd02201e8) = (BTDIGITAL_REG(0xd02201e8) & (~0x7c0)) | 0x380;
  BTDIGITAL_REG(0xd0350360) = 0x003fe040;
  BTDIGITAL_REG(0xd0220470) |= 0x40;

#ifdef __CLK_GATE_DISABLE__
  BTDIGITAL_REG(0xD0330024) &= (~0x00020);
  BTDIGITAL_REG(0xD0330024) |= 0x40000;
  BTDIGITAL_REG(0xD0330038) |= 0x200000;
#endif

#ifdef LBRT
  BTDIGITAL_REG(0xd0350300) = 0x00000000;
  BTDIGITAL_REG(0xd0350340) = 0x00000000;
#else
#ifdef __BDR_EDR_2DB__
  BTDIGITAL_REG(0xd0350300) = 0x55;
  BTDIGITAL_REG(0xd0350308) = 0x00003C0F;
#else
  BTDIGITAL_REG(0xd0350300) = 0x11;
#endif
  BTDIGITAL_REG(0xd0350340) = 0x1;
#endif
  // 0x07 will affect Bluetooth sensitivity
  // 0x06 will lead to LBRT rx bad in close distance
  BTDIGITAL_REG(0xd0350280) = 0x00000006;
  BTDIGITAL_REG(0xd035031c) = 0x00050004; // modulation factor 17/16
  BTDIGITAL_REG(0xd0350320) = 0x00350011; // added by xrz 2018.10.10
  BTDIGITAL_REG(0xd0220080) = 0x0e571439; // trx pwrup/dn
  BTDIGITAL_REG(0xd0220280) = 0x0e471445; // add by luobin 2019/05/23

  BTDIGITAL_REG(0xd0350210) = 0x00f10040; // add by walker 2018/12/27
  BTDIGITAL_REG(0xd03502c4) = 0x127f02ef; // 2M TE time init
  BTDIGITAL_REG(0xd0350284) = 0x02000200;
  BTDIGITAL_REG_SET_FIELD(0xd0220200, 7, 0, 3);

  BTDIGITAL_REG(0xd0350398) = 0xD25EF79C;
  BTDIGITAL_REG(0xd035039c) = 0x60C6C061; // hwagc config

  BTDIGITAL_REG(0xd03503a8) = 0x14666E88; // hwagc config
  BTDIGITAL_REG(0xd0350364) = 0x002EB948; // data sign and iq swap
  BTDIGITAL_REG(0xd03503a0) =
      0x1c070055; // improve 1M RX sensitivity by jiangpeng

  // for system 2M Band Wide
  BTDIGITAL_REG(0x4008003c) |= 1;
  BTDIGITAL_REG(0x40080018) |= 1;
  BTDIGITAL_REG(0x40080004) |= (1 << 15) | (1 << 30); // osc x4 enable
  BTDIGITAL_REG(0xd0330038) |= (3 << 6) | (1 << 11);
  BTDIGITAL_REG(0xd03300f0) |= 1;

  // for IBRT fast ack
  BTDIGITAL_REG(0xd0220464) |= 1 << 29;    // fast ack 2M mode enable
  BTDIGITAL_REG(0xd0220468) = 0x00403832;  // 2M fast ack timings
  BTDIGITAL_REG(0xd022046c) &= ~(1 << 31); // enable DM1 empty fastack
  BTDIGITAL_REG(0xd035020C) = 0x00f1002c;
  BTDIGITAL_REG(0xD0350210) = 0x00f1082c; // tx guard
  BTDIGITAL_REG(0xd0220498) = 0x00A01991; // fast ack timeout
}

extern const uint8_t lmp_sniffer_filter_tab[51];
extern const uint8_t lmp_ext_sniffer_filter_tab[18];
extern const uint8_t lmp_ext_sniffer_fast_cfm_tab[4];
void bt_drv_config_lmp_filter_table(void) {
  if (hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_1) {
    BTDIGITAL_REG(0xc0000300) = 0xc00070f4;
    BT_DRV_TRACE(2, "%s: 0x%x", __func__, BTDIGITAL_REG(0xc0000300));
    memcpy((uint8_t *)(0xc00070f4), lmp_sniffer_filter_tab,
           sizeof(lmp_sniffer_filter_tab));
  } else if (hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_2) {
    BTDIGITAL_REG(0xc0000314 + 4) = 0xC0006e40;
    memcpy((uint8_t *)(0xC0006e40), lmp_ext_sniffer_filter_tab,
           sizeof(lmp_ext_sniffer_filter_tab));
    BTDIGITAL_REG(0xc0000314 + 0xc) = 0xC0006c9c;
    BT_DRV_TRACE(3, "%s: 0x%x, 0x%x", __func__, BTDIGITAL_REG(0xc0000314 + 4),
                 BTDIGITAL_REG(0xc0000314 + 0xc));
    memcpy((uint8_t *)(0xC0006c9c), lmp_ext_sniffer_fast_cfm_tab,
           sizeof(lmp_ext_sniffer_fast_cfm_tab));
  }
}

uint32_t ld_ibrt_sco_req_filter_patch[] = {
    0x7981b470, /*76c0*/
    0xf1034b0b, 0xe0020410, 0x42a33304, 0x785ad00c, 0xd1f9428a, 0x789a7a06,
    0xd1f54296, 0x78da8946, 0xd1f14296, 0xe0002001, 0xbc702000, 0xbf004770,
    0xc0007450, // sniffer_sco_filter
};

void bt_drv_func_ld_ibrt_sco_req_filter(void) {
  if (hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_2) {
    memcpy((uint32_t *)(0xc00076c0), ld_ibrt_sco_req_filter_patch,
           sizeof(ld_ibrt_sco_req_filter_patch));
  }
}

extern void bt_drv_reg_op_controller_mem_log_config(void);
void btdrv_config_init(void) {
  BT_DRV_TRACE(1, "%s", __func__);

  if (btdrv_get_lmp_trace_enable()) {
    // enable lmp trace
    bt_lmp_record[0] = 1;
    bt_lmp_record[1] = 1;
    btdrv_cfg_tbl[0].is_act = BTDRV_CONFIG_ACTIVE;
    ASSERT((btdrv_cfg_tbl[0].opcode == HCI_DBG_LMP_MESSAGE_RECORD_CMD_OPCODE),
           "lmp config not match");
  }

  if (btdrv_get_controller_trace_level() != BTDRV_INVALID_TRACE_LEVEL) {
    // enable controller trace
    bt_setting_2300p[28] = btdrv_get_controller_trace_level();
    bt_setting_2300p_t2[28] = btdrv_get_controller_trace_level();
  }

  for (uint8_t i = 0; i < sizeof(btdrv_cfg_tbl) / sizeof(btdrv_cfg_tbl[0]);
       i++) {
    if (btdrv_cfg_tbl[i].opcode == HCI_DBG_SET_BT_SETTING_CMD_OPCODE) {
      if (hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_0 &&
          btdrv_cfg_tbl[i].parlen == sizeof(bt_setting_2300p)) {
        btdrv_send_cmd(btdrv_cfg_tbl[i].opcode, btdrv_cfg_tbl[i].parlen,
                       btdrv_cfg_tbl[i].param);
        btdrv_delay(1);
      } else if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_1 &&
                 btdrv_cfg_tbl[i].parlen == sizeof(bt_setting_2300p_t2)) {
        btdrv_send_cmd(btdrv_cfg_tbl[i].opcode, btdrv_cfg_tbl[i].parlen,
                       btdrv_cfg_tbl[i].param);
        btdrv_delay(1);
      }
    }

    if (btdrv_cfg_tbl[i].opcode == HCI_DBG_SET_BT_SETTING_EXT1_CMD_OPCODE) {
      if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_2 &&
          btdrv_cfg_tbl[i].parlen == sizeof(bt_setting_ext1_2300p_t3)) {
        btdrv_send_cmd(btdrv_cfg_tbl[i].opcode, btdrv_cfg_tbl[i].parlen,
                       btdrv_cfg_tbl[i].param);
        btdrv_delay(1);
      }
    }
    // BT other config
    if (btdrv_cfg_tbl[i].is_act == BTDRV_CONFIG_ACTIVE) {
      btdrv_send_cmd(btdrv_cfg_tbl[i].opcode, btdrv_cfg_tbl[i].parlen,
                     btdrv_cfg_tbl[i].param);
      btdrv_delay(1);
    }
  }

  // BT registers config
  for (uint8_t i = 0;
       i < sizeof(mem_config_2300p) / sizeof(mem_config_2300p[0]); i++) {
    btdrv_write_memory(_32_Bit, mem_config_2300p[i][0],
                       (uint8_t *)&mem_config_2300p[i][1], 4);
    btdrv_delay(1);
  }

  if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_0) {
    btdrv_digital_config_init_2300p_t1();
    if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_1) {
      btdrv_digital_config_init_2300p_t2();
    }
  }

  if (btdrv_get_controller_trace_dump_enable()) {
    bt_drv_reg_op_controller_mem_log_config();
  }

  bt_drv_config_lmp_filter_table();
  bt_drv_func_ld_ibrt_sco_req_filter();
  bt_drv_set_fa_invert_enable(BT_FA_INVERT_EN);
}

// zhangzhd agc config use default 1216

#define RX_GAIN_STEP0 -77
#define RX_GAIN_STEP1 -72
#define RX_GAIN_STEP2 -67
#define RX_GAIN_STEP3 -62
#define RX_GAIN_STEP4 -57
#define RX_GAIN_STEP5 -52
#define RX_GAIN_STEP6 -47
// zhangzhd agc config use default 1216 end

void bt_drv_adaptive_fa_rx_gain(int8_t rssi) {
#ifdef __FA_RX_GAIN_CTRL__
  uint8_t gain_step = 0xff;
  static uint8_t old_step = 0xff;

  if (rssi <= RX_GAIN_STEP0) {
    gain_step = 0;
  } else if (rssi <= RX_GAIN_STEP1) {
    gain_step = 1;
  } else if (rssi <= RX_GAIN_STEP2) {
    gain_step = 2;
  } else if (rssi <= RX_GAIN_STEP3) {
    gain_step = 3;
  } else if (rssi <= RX_GAIN_STEP4) {
    gain_step = 4;
  } else if (rssi <= RX_GAIN_STEP5) {
    gain_step = 5;
  } else if (rssi <= RX_GAIN_STEP6) {
    gain_step = 6;
  } else {
    gain_step = 7;
  }

  if (old_step != gain_step) {
    BT_DRV_TRACE(2, "if rssi = %d,then set fa %d level ", rssi, gain_step);
    BT_DRV_REG_OP_ENTER();
    bt_drv_reg_op_fa_gain_direct_set(gain_step);
    BT_DRV_REG_OP_EXIT();
    old_step = gain_step;
  }
#endif
}

bool btdrv_is_ecc_enable(void) {
  bool ret = false;
#ifdef __FASTACK_ECC_ENABLE__
  ret = true;
#endif
  return ret;
}

#ifdef LAURENT_ALGORITHM
void btdrv_bt_laurent_algorithm_enable(void) {
  if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_0) {
    BT_DRV_TRACE(1, "%s", __func__);
    BTDIGITAL_REG(0xd03503a8) = 0x14664E88;
    BTDIGITAL_REG(0xd0350240) = 0x0001A40F;
    BTDIGITAL_REG(0xd0350364) = 0x202EB948; // lau_gain
    BTDIGITAL_REG(0xd0350374) = 0x00A40DCD; // c1c2 0x06001e0
    BTDIGITAL_REG(0xd0350228) = 0x12040800; // clkmode
    BTDIGITAL_REG(0xd03503C8) = 0x00840CCD; // train c1c2
    BTDIGITAL_REG(0xd03503A0) = 0x1C070065; // new corr en
    BTDIGITAL_REG(0xd0220460) = 0x039EF088; // mac laurent_en
    BTDIGITAL_REG(0xd0350370) = 0x6B240A3D; // laurent_en  0x
    BTDIGITAL_REG(0xd0350280) = 0x00000007; // bt_dfe_forcera
    BTDIGITAL_REG(0xd03502C4) = 0x127F02E8; // te_timeinit
  }
}

void btdrv_ble_laurent_algorithm_enable(void) {
  if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_0) {
    BT_DRV_TRACE(1, "%s", __func__);
    BTDIGITAL_REG(0xd0350370) = 0x63240A3D; // lp disable
    BTDIGITAL_REG(0xd0350280) = 0x00000007; // dfe_forceraw=0 psd_avgen=1
  }
}
#endif

////////////////////////////////////////test
/// mode////////////////////////////////////////////

void btdrv_sleep_config(uint8_t sleep_en) {
  sleep_param[0] = sleep_en;
  btdrv_send_cmd(HCI_DBG_SET_SLEEP_SETTING_CMD_OPCODE, 8, sleep_param);
  btdrv_delay(1);
}

void btdrv_feature_default(void) {
  const uint8_t feature[] = {0xBF, 0xeE, 0xCD, 0xFe, 0xc3, 0xFf, 0x7b, 0x87};
  btdrv_send_cmd(HCI_DBG_SET_LOCAL_FEATURE_CMD_OPCODE, 8, feature);
  btdrv_delay(1);
}

const uint8_t test_mode_addr[6] = {0x77, 0x77, 0x77, 0x77, 0x77, 0x77};
void btdrv_test_mode_addr_set(void) {
  return;

  btdrv_send_cmd(HCI_DBG_SET_BD_ADDR_CMD_OPCODE, sizeof(test_mode_addr),
                 test_mode_addr);
  btdrv_delay(1);
}

uint8_t meInit_param_get_entry_idx = 0;

int btdrv_meinit_param_init(void) {
  int size = 0;
  if ((me_init_param[0][0] == 0xffffffff) &&
      (me_init_param[0][1] == 0xffffffff)) {
    size = -1;
  }
  meInit_param_get_entry_idx = 0;
  return size;
}

int btdrv_meinit_param_remain_size_get(void) {
  int remain_size;
  if ((me_init_param[0][0] == 0xffffffff) &&
      (me_init_param[0][1] == 0xffffffff)) {
    return -1;
  }
  remain_size = ARRAY_SIZE(me_init_param) - meInit_param_get_entry_idx;
  return remain_size;
}

int btdrv_meinit_param_next_entry_get(uint32_t *addr, uint32_t *val) {
  if (meInit_param_get_entry_idx > (ARRAY_SIZE(me_init_param) - 1))
    return -1;
  *addr = me_init_param[meInit_param_get_entry_idx][0];
  *val = me_init_param[meInit_param_get_entry_idx][1];
  meInit_param_get_entry_idx++;
  return 0;
}

enum {
  SYNC_IDLE,
  SYNC_64_ORG,
  SYNC_68_ORG,
  SYNC_72_ORG,
  SYNC_64_NEW,
  SYNC_68_NEW,
  SYNC_72_NEW,
};

enum {
  SYNC_64_BIT,
  SYNC_68_BIT,
  SYNC_72_BIT,
};

uint32_t bt_sync_type = SYNC_IDLE;
void btdrv_sync_config(void) {
  uint32_t corr_mode = BTDIGITAL_REG(0xd0220460);
  uint32_t dfe_mode = BTDIGITAL_REG(0xd0350360);
  uint32_t timeinit = BTDIGITAL_REG(0xd03502c4);
  if (bt_sync_type == SYNC_IDLE)
    return;

  corr_mode = (corr_mode & 0xfffffff8); // bit2: enh dfe; [1:0]: bt_corr_mode
  dfe_mode = (dfe_mode &
              0xffffffe0); // bit4: dfe_header_mode_bt; [3:0]: dfe_delay_cycle
  timeinit = (timeinit & 0xfffff800); //[10:0]: tetimeinit value

  switch (bt_sync_type) {
  case SYNC_64_ORG:
    corr_mode |= 0x0;
    dfe_mode |= 0x00;
    timeinit |= 0x2eb;
    break;
  case SYNC_68_ORG:
    corr_mode |= 0x1;
    dfe_mode |= 0x00;
    timeinit |= 0x2eb;
    break;
  case SYNC_72_ORG:
    corr_mode |= 0x2;
    dfe_mode |= 0x00;
    timeinit |= 0x2b7;
    break;
  case SYNC_64_NEW:
    corr_mode |= 0x4;
    dfe_mode |= 0x14;
    timeinit |= 0x2eb;
    break;
  case SYNC_68_NEW:
    corr_mode |= 0x5;
    dfe_mode |= 0x14;
    timeinit |= 0x2eb;
    break;
  case SYNC_72_NEW:
    corr_mode |= 0x6;
    dfe_mode |= 0x10;
    timeinit |= 0x2b7;
    break;
  }
  BTDIGITAL_REG(0xd0220460) = corr_mode;
  BTDIGITAL_REG(0xd0350360) = dfe_mode;
  BTDIGITAL_REG(0xd03502c4) = timeinit;
}
// HW SPI TRIG

#define REG_SPI_TRIG_SELECT_LINK0_ADDR EM_BT_BT_EXT1_ADDR // 114a+66
#define REG_SPI_TRIG_SELECT_LINK1_ADDR                                         \
  (EM_BT_BT_EXT1_ADDR + BT_EM_SIZE) // 11b8+66
#define REG_SPI_TRIG_NUM_ADDR 0xd0220400
#define REG_SPI0_TRIG_POS_ADDR 0xd0220454
#define REG_SPI1_TRIG_POS_ADDR 0xd0220458

struct SPI_TRIG_NUM_T {
  uint32_t spi0_txon_num : 3;  // spi0 number of tx rising edge
  uint32_t spi0_txoff_num : 3; // spi0 number of tx falling edge
  uint32_t spi0_rxon_num : 2;  // spi0 number of rx rising edge
  uint32_t spi0_rxoff_num : 2; // spi0 number of rx falling edge
  uint32_t spi0_fast_mode : 1;
  uint32_t spi0_gap : 4;
  uint32_t hwspi0_en : 1;
  uint32_t spi1_txon_num : 3;  // spi1 number of tx rising edge
  uint32_t spi1_txoff_num : 3; // spi1 number of tx falling edge
  uint32_t spi1_rxon_num : 2;  // spi1 number of rx rising edge
  uint32_t spi1_rxoff_num : 2; // spi1 number of rx falling edge
  uint32_t spi1_fast_mode : 1;
  uint32_t spi1_gap : 4;
  uint32_t hwspi1_en : 1;
};

struct SPI_TRIG_POS_T {
  uint32_t spi_txon_pos : 7;
  uint32_t spi_txoff_pos : 9;
  uint32_t spi_rxon_pos : 7;
  uint32_t spi_rxoff_pos : 9;
};

struct spi_trig_data {
  uint32_t reg;
  uint32_t value;
};

static const struct spi_trig_data spi0_trig_data_tbl[] = {
    //{addr,data([23:0])}
    {0xd0220404, 0x8080e9}, // spi0_trig_txdata1
    {0xd0220408, 0x000000}, // spi0_trig_txdata2
    {0xd022040c, 0x000000}, // spi0_trig_txdata3
    {0xd0220410, 0x000000}, // spi0_trig_txdata4
#ifdef __FA_RX_GAIN_CTRL__
    {0xd022041c, 0x0094bf}, // spi0_trig_rxdata1
#else
    {0xd022041c, 0x000000}, // spi0_trig_rxdata1
#endif
    {0xd0220420, 0x000000}, // spi0_trig_rxdata2
    {0xd0220424, 0x000000}, // spi0_trig_rxdata3
    {0xd0220428, 0x000000}, // spi0_trig_rxdata4
    {0xd0220414, 0x000000}, // spi0_trig_trxdata5
    {0xd0220418, 0x000000}, // spi0_trig_trxdata6
};

static const struct spi_trig_data spi1_trig_data_tbl[] = {
//{addr,data([23:0])}
#ifdef __FA_RX_GAIN_CTRL__
    {0xd022042c, 0x8080e9}, // spi1_trig_txdata1
#else
    {0xd022042c, 0x000000}, // spi1_trig_txdata1
#endif
    {0xd0220430, 0x000000}, // spi1_trig_txdata2
    {0xd0220434, 0x000000}, // spi1_trig_txdata3
    {0xd0220438, 0x000000}, // spi1_trig_txdata4
#ifdef __FA_RX_GAIN_CTRL__
    {0xd0220444, 0x0094bf}, // spi1_trig_rxdata1
#else
    {0xd0220444, 0x000000}, // spi1_trig_rxdata1
#endif
    {0xd0220448, 0x000000}, // spi1_trig_rxdata2
    {0xd022044c, 0x000000}, // spi1_trig_rxdata3
    {0xd0220450, 0x000000}, // spi1_trig_rxdata4
    {0xd022043c, 0x000000}, // spi1_trig_trxdata5
    {0xd0220440, 0x000000}, // spi1_trig_trxdata6
};

void btdrv_spi_trig_data_change(uint8_t spi_sel, uint8_t index,
                                uint32_t value) {
  if (!spi_sel) {
    BTDIGITAL_REG(spi0_trig_data_tbl[index].reg) = value & 0xFFFFFF;
  } else {
    BTDIGITAL_REG(spi1_trig_data_tbl[index].reg) = value & 0xFFFFFF;
  }
}

void btdrv_spi_trig_data_set(uint8_t spi_sel) {
  if (!spi_sel) {
    for (uint8_t i = 0; i < ARRAY_SIZE(spi0_trig_data_tbl); i++) {
      BTDIGITAL_REG(spi0_trig_data_tbl[i].reg) = spi0_trig_data_tbl[i].value;
    }
  } else {
    for (uint8_t i = 0; i < ARRAY_SIZE(spi1_trig_data_tbl); i++) {
      BTDIGITAL_REG(spi1_trig_data_tbl[i].reg) = spi1_trig_data_tbl[i].value;
    }
  }
}

void btdrv_spi_trig_num_set(uint8_t spi_sel,
                            struct SPI_TRIG_NUM_T *spi_trig_num) {
  uint8_t tx_onoff_total_num;
  uint8_t rx_onoff_total_num;

  if (!spi_sel) {
    tx_onoff_total_num =
        spi_trig_num->spi0_txon_num + spi_trig_num->spi0_txoff_num;
    rx_onoff_total_num =
        spi_trig_num->spi0_rxon_num + spi_trig_num->spi0_rxoff_num;
  } else {
    tx_onoff_total_num =
        spi_trig_num->spi1_txon_num + spi_trig_num->spi1_txoff_num;
    rx_onoff_total_num =
        spi_trig_num->spi1_rxon_num + spi_trig_num->spi1_rxoff_num;
  }
  ASSERT((tx_onoff_total_num <= 6), "spi trig tx_onoff_total_num>6");
  ASSERT((rx_onoff_total_num <= 6), "spi trig rx_onoff_total_num>6");

  BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) = *(uint32_t *)spi_trig_num;
}

void btdrv_spi_trig_pos_set(uint8_t spi_sel,
                            struct SPI_TRIG_POS_T *spi_trig_pos) {
  if (!spi_sel) {
    BTDIGITAL_REG(REG_SPI0_TRIG_POS_ADDR) = *(uint32_t *)spi_trig_pos;
  } else {
    BTDIGITAL_REG(REG_SPI1_TRIG_POS_ADDR) = *(uint32_t *)spi_trig_pos;
  }
}

#ifdef __FA_RX_GAIN_CTRL__
void btdrv_spi_trig_init(void) {
  struct SPI_TRIG_NUM_T spi_trig_num;
  struct SPI_TRIG_POS_T spi0_trig_pos;
  struct SPI_TRIG_POS_T spi1_trig_pos;

  spi_trig_num.spi0_txon_num = 0;
  spi_trig_num.spi0_txoff_num = 0;
  spi_trig_num.spi0_rxon_num = 1;
  spi_trig_num.spi0_rxoff_num = 0;
  spi_trig_num.spi0_fast_mode = 0;
  spi_trig_num.spi0_gap = 4;
  spi_trig_num.hwspi0_en = 1;

  spi_trig_num.spi1_txon_num = 0;
  spi_trig_num.spi1_txoff_num = 1;
  spi_trig_num.spi1_rxon_num = 1;
  spi_trig_num.spi1_rxoff_num = 0;
  spi_trig_num.spi1_fast_mode = 0;
  spi_trig_num.spi1_gap = 4;
  spi_trig_num.hwspi1_en = 1;

  btdrv_spi_trig_num_set(0, &spi_trig_num);
  btdrv_spi_trig_num_set(1, &spi_trig_num);

  spi0_trig_pos.spi_txon_pos = 0;
  spi0_trig_pos.spi_txoff_pos = 0;
  spi0_trig_pos.spi_rxon_pos = 25;
  spi0_trig_pos.spi_rxoff_pos = 0;

  spi1_trig_pos.spi_txon_pos = 0;
  spi1_trig_pos.spi_txoff_pos = 0;
  spi1_trig_pos.spi_rxon_pos = 110;
  spi1_trig_pos.spi_rxoff_pos = 0;

  btdrv_spi_trig_pos_set(0, &spi0_trig_pos);
  btdrv_spi_trig_pos_set(1, &spi1_trig_pos);

  btdrv_spi_trig_data_set(0);
  btdrv_spi_trig_data_set(1);
}
#else
void btdrv_spi_trig_init(void) {
  struct SPI_TRIG_NUM_T spi_trig_num;
  struct SPI_TRIG_POS_T spi0_trig_pos;
  struct SPI_TRIG_POS_T spi1_trig_pos;

  spi_trig_num.spi0_txon_num = 0;
  spi_trig_num.spi0_txoff_num = 1;
  spi_trig_num.spi0_rxon_num = 0;
  spi_trig_num.spi0_rxoff_num = 0;
  spi_trig_num.spi0_fast_mode = 0;
  spi_trig_num.spi0_gap = 4;
  spi_trig_num.hwspi0_en = 0;

  spi_trig_num.spi1_txon_num = 0;
  spi_trig_num.spi1_txoff_num = 0;
  spi_trig_num.spi1_rxon_num = 0;
  spi_trig_num.spi1_rxoff_num = 0;
  spi_trig_num.spi1_fast_mode = 0;
  spi_trig_num.spi1_gap = 0;
  spi_trig_num.hwspi1_en = 0;

  btdrv_spi_trig_num_set(0, &spi_trig_num);
  btdrv_spi_trig_num_set(1, &spi_trig_num);

  spi0_trig_pos.spi_txon_pos = 0;
  spi0_trig_pos.spi_txoff_pos = 20;
  spi0_trig_pos.spi_rxon_pos = 0;
  spi0_trig_pos.spi_rxoff_pos = 0;

  spi1_trig_pos.spi_txon_pos = 0;
  spi1_trig_pos.spi_txoff_pos = 0;
  spi1_trig_pos.spi_rxon_pos = 0;
  spi1_trig_pos.spi_rxoff_pos = 0;

  btdrv_spi_trig_pos_set(0, &spi0_trig_pos);
  btdrv_spi_trig_pos_set(1, &spi1_trig_pos);

  btdrv_spi_trig_data_set(0);
  btdrv_spi_trig_data_set(1);
}
#endif

void btdrv_spi_trig_select(uint8_t link_id, bool spi_set) {
  BTDIGITAL_BT_EM(EM_BT_BT_EXT1_ADDR + link_id * BT_EM_SIZE) |= (spi_set << 14);
}

uint8_t btdrv_get_spi_trig_enable(uint8_t spi_sel) {
  if (!spi_sel) {
    return ((BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) & 0x8000) >> 15);
  } else {
    return ((BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) & 0x80000000) >> 31);
  }
}

void btdrv_set_spi_trig_enable(uint8_t spi_sel) {
  if (!spi_sel) {
    BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) |= (1 << 15); // spi0
  } else {
    BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) |= (1 << 31); // spi1
  }
}

void btdrv_clear_spi_trig_enable(uint8_t spi_sel) {
  if (!spi_sel) {
    BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) &= ~0x8000;
  } else {
    BTDIGITAL_REG(REG_SPI_TRIG_NUM_ADDR) &= ~0x80000000;
  }
}

bool btdrv_get_lmp_trace_enable(void) { return g_lmp_trace_enable; }
void btdrv_set_lmp_trace_enable(void) { g_lmp_trace_enable = true; }
void btdrv_set_controller_trace_enable(uint8_t trace_level) {
  g_controller_trace_level = trace_level;
}

uint8_t btdrv_get_controller_trace_level(void) {
  return g_controller_trace_level;
}

void btdrv_fast_lock_config(bool fastlock_on) {
  uint16_t val = 0;

  if (fastlock_on) {
    btdrv_read_rf_reg(0x1AE, &val);
    btdrv_write_rf_reg(0x1AE, val | (1 << 9) | (1 << 11));
    BTDIGITAL_REG(0xd0220468) |= 1 << 26; // fast lock enable
  } else {
    btdrv_read_rf_reg(0x1AE, &val);
    btdrv_write_rf_reg(0x1AE, val & (~((1 << 9) | (1 << 11))));
    BTDIGITAL_REG(0xd0220468) &= (~(1 << 26)); // fast lock disable
  }
}

#ifdef __FASTACK_ECC_ENABLE__
void btdrv_ecc_config(void) {
#define INVALID 0xff
#define ECC_8PSK 0
#define ECC_DPSK 1
#define ECC_GFSK 2

#define ECC_1BLOCK 0
#define ECC_2BLOCK 1
#define ECC_3BLOCK 2

  const uint32_t fa_2m = 0;
  const uint32_t fastlock_on = 0;
  const uint32_t bt_sys_52m_en = 0;
  const uint32_t ecc_mode_enable = 0;
  const uint32_t ecc_psk_mode = ECC_DPSK;
  const uint32_t ecc_blk_mode = ECC_3BLOCK;

  if (bt_sys_52m_en) {
    BTDIGITAL_REG(0x4008003c) |= 1;
    BTDIGITAL_REG(0x40080018) |= 1;
    BTDIGITAL_REG(0x40080004) |= (1 << 15) | (1 << 30); // osc x4 enable
    BTDIGITAL_REG(0xd0330038) |= (3 << 6) | (1 << 11);
    BTDIGITAL_REG(0xd03300f0) |= 1;
  }

  if (fa_2m) {
    BTDIGITAL_REG(0xd0220464) |= 1 << 29; // fast ack 2M mode enable 1, disable
                                          // 0
  } else {
    BTDIGITAL_REG(0xd0220464) &=
        (~(1 << 29)); // fast ack 2M mode enable 1, disable 0
  }

  // 1302:  RF 0x1AE[9] = 1;
  // 1402:  RF 0x64[15] = 1;

  BTDIGITAL_REG(0xd0330038) |= (1 << 9); // jiangpeng test result ok
  btdrv_fast_lock_config(fastlock_on);
  if (fastlock_on) {
    if (fa_2m)
      BTDIGITAL_REG_SET_FIELD(0xd0220468, 0xffff, 0, 0x1914);
    else
      BTDIGITAL_REG_SET_FIELD(0xd0220468, 0xffff, 0, 0x1e14);
  } else {
    if (fa_2m)
      BTDIGITAL_REG_SET_FIELD(0xd0220468, 0xffff, 0, 0x3530);
    else
      BTDIGITAL_REG_SET_FIELD(0xd0220468, 0xffff, 0, 0x3528);
  }

  if (ecc_mode_enable) {
    BTDIGITAL_REG(0xd0220464) |= (0x1 << 15);   ////enable ecc mode
    BTDIGITAL_REG(0xd0220464) &= ~(0x1F << 24); // ecc time adj
    BTDIGITAL_REG(0xd0220464) |= (0x1 << 25);   ////en ecc time adj

    if (ecc_psk_mode == ECC_8PSK) {
      BTDIGITAL_REG_SET_FIELD(0xd02204a8, 3, 13, 3); // ECC 8PSK
    } else if (ecc_psk_mode == ECC_DPSK) {
      BTDIGITAL_REG_SET_FIELD(0xd02204a8, 3, 13, 2); // ECC DPSK
    } else if (ecc_psk_mode == ECC_GFSK) {
      BTDIGITAL_REG_SET_FIELD(0xd02204a8, 3, 13, 1); // ECC GFSK
    }

    if (ecc_blk_mode == ECC_1BLOCK) {
      BTDIGITAL_REG(0xd022048c) &= ~0x3ff;
      BTDIGITAL_REG(0xd022048c) |= 0xef; // set ecc len  ECC 1 block
    } else if (ecc_blk_mode == ECC_2BLOCK) {
      BTDIGITAL_REG(0xd022048c) &= ~0x3ff;
      BTDIGITAL_REG(0xd022048c) |= 0x1de; // set ecc len,  ECC 2 block
    } else if (ecc_blk_mode == ECC_3BLOCK) {
      BTDIGITAL_REG(0xd022048c) &= ~0x3ff;
      BTDIGITAL_REG(0xd022048c) |= 0x2cd; // set ecc len ECC 3 block
    }
  } else {
    BTDIGITAL_REG(0xd0220464) &= (~(0x1 << 15)); ////disable ecc mode
  }
}
#endif

void btdrv_hw_agc_stop_mode(enum BT_SYNCMODE_REQ_USER_T user,
                            bool hw_agc_mode) {
#ifdef __HW_AGC__
  static uint8_t bt_syncmode_map = 0;

  uint32_t lock;

  lock = int_lock();
  uint32_t reg_val = BTDIGITAL_REG(0xd03503a8);

  if (hw_agc_mode) {
    if (bt_syncmode_map == 0) {
      // set bit28 0 : rx win timeout, stop agc
      reg_val &= ~(1 << 28);
      BTDIGITAL_REG(0xd03503a8) = reg_val;
    }
    bt_syncmode_map |= (1 << user);
  } else {
    bt_syncmode_map &= ~(1 << user);
    if (bt_syncmode_map == 0) {
      // set bit28 1 : sync find, stop agc
      reg_val |= (1 << 28);
      BTDIGITAL_REG(0xd03503a8) = reg_val;
    }
  }
  int_unlock(lock);

#endif
}