/*
 * Copyright 2020-2021 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#ifndef NXP_XCVR_LCL_CTRL_H
/* clang-format off */
#define NXP_XCVR_LCL_CTRL_H
/* clang-format on */

#include "fsl_common.h"
#include "nxp2p4_xcvr.h"
#include "nxp_xcvr_ext_ctrl.h"      /* Include support for antenna control and pattern match */
#include "nxp_xcvr_lcl_config.h"    /* RSM timing configurations */

/*!
 * @addtogroup xcvr_localization Localization Routines
 * @{
 */

#define CONNRF_1163_IF_COMP 1

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#if defined(__cplusplus)
    extern "C" {
#endif
    
#if defined(RADIO_IS_GEN_4P5)  && (RF_OSC_26MHZ == 0) /* RSM only supported on Gen 4.5 radios & with RF_OSC = 32MHz */

/* Long (64 bit) PN support is disabled by default but can be enabled at project level */
 #ifndef SUPPORT_RSM_LONG_PN
 #define SUPPORT_RSM_LONG_PN        (0)
 #endif /* SUPPORT_RSM_LONG_PN */
 
#define NUM_TSM_U32_REGISTERS   (sizeof(XCVR_TSM_Type)/4U)

#define XCVR_RSM_OVERALL_MAX_SEQ_LEN     (128U)      /*!< Maximum overall sequence length (inclusive) for RSM sequences. No sequence can be longer than this due to Fstep RAM array size. */
#define XCVR_RSM_FCS_PKPK_MAX_STEP_COUNT (106U)      /*!< Maximum number of FCS, Pk-Pk, or Pk-Tn-Tn-Pk steps within any RSM sequence.  This is due to PN and RTT RAM array sizes. */
#define XCVR_RSM_MIN_SEQ_LEN             (1U)        /*!< Minimum sequence length (inclusive) for RSM sequences */
#define XCVR_RSM_MAX_NUM_ANT             (32U)        /*!< Maximum number of antennae supported by LCL Antenna Control (assumes external decode logic).  */

#define RSM_PCBD_RAM        (RX_PACKET_RAM_BASE)        /*!< Coarse Tune Best Diff Buffer Base Address */
#define RSM_PCBD_ENTRY_SZ   (1U)                        /*!< Size (bytes) of one entry in the Coarse Tune Best Diff Buffer  */
#define RSM_PCBD_RAM_COUNT  (128U)                      /*!< Coarse Tune Best Diff Buffer count of elements */
#define RSM_RTT_RAM         (RX_PACKET_RAM_BASE+0x80U)  /*!< Round Trip Time Buffer Base Address */
#define RSM_RTT_RAM_ENTRY_SZ (4U)                        /*!< Size (bytes) of one entry in the Round Trip Time Buffer */
#define RSM_RTT_RAM_COUNT   (424U/RSM_RTT_RAM_ENTRY_SZ)  /*!< Round Trip Time Buffer count of elements */
#define RSM_PN_RAM          (RX_PACKET_RAM_BASE+0x230U)  /*!< PN (both 32 and 64) Buffer Base Address */
#define RSM_PN_RAM_32_ENTRY_SZ (8U)                      /*!< Size (bytes) of one entry in the PN  32  Buffer  */
#define RSM_PN_RAM_32_COUNT (848U/RSM_PN_RAM_32_ENTRY_SZ) /*!< PN  32  Buffer count of elements */
#if defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1)
#define RSM_PN_RAM_64_ENTRY_SZ (16U)                     /*!< Size (bytes) of one entry in the PN  64  Buffer  */
#define RSM_PN_RAM_64_COUNT (848U/RSM_PN_RAM_64_ENTRY_SZ) /*!< PN  64  Buffer count of elements */
#endif /* defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1) */
#define RSM_FSTEP_RAM       (RX_PACKET_RAM_BASE+0x580U)  /*!< Frequency Step Buffer Base Address */
#define RSM_FSTEP_ENTRY_SZ  (5U)                         /*!< Size (bytes) of one entry in the  Frequency Step Buffer */
#define RSM_FSTEP_RAM_COUNT (640U/RSM_FSTEP_ENTRY_SZ)    /*!< Frequency Step Buffer count of elements */

#define GAMMA_ROWS          (6U)                         /*!< Number of rows in Gamma array for RTT fractional delay estimation */
#define GAMMA_COLS          (4U)                         /*!< Number of columns in Gamma array for RTT fractional delay estimation */

#define BLE_MIN_FREQ 2402U
#define BLE_MAX_FREQ 2480U
#define RSM_HADM_MAX_CHAN_INDEX 78U /*!< HADM channel indexes run from 0 to 78 to represent frequencies 2402 to 2480MHz in 1MHz increments */

#define T_RD                (5U)

/*! @brief  RSM control mode settings. */
typedef enum
{
    XCVR_RSM_SQTE_MODE       = 0U, /*!< Secure Quick Tone Exchange mode (AKA HADM) */
    XCVR_RSM_PDE_MODE        = 1U,  /*!< Phase Distance Estimation mode */
    XCVR_RSM_MODE_INVALID /* Must always be last! */
}   XCVR_RSM_MODE_T;

/*! @brief  RSM RX/TX mode settings. */
typedef enum
{
    XCVR_RSM_RX_MODE       = 0U, /*!< Configure RSM to start with Receive. AKA the SQTE "Reflector" role or the PDE "RD" role */
    XCVR_RSM_TX_MODE       = 1U,  /*!<  Configure RSM to start with Transmit. AKA the SQTE "Initiator" role or the PDE "MD" role */
    XCVR_RSM_RXTX_MODE_INVALID /* Must always be last! */
}   XCVR_RSM_RXTX_MODE_T;

/*! @brief  RSM Trigger Selection  settings. */
typedef enum
{
    XCVR_RSM_TRIG_SW            = 0U,  /*!< Trigger the RSM module immediately (software triggered). */
    XCVR_RSM_TRIG_CRC_VLD       = 1U,  /*!<  Trigger the RSM module upon CRC Valid detection. */
    XCVR_RSM_TRIG_AA_FND        = 2U,  /*!<  Trigger the RSM module upon Access Address detection from the PHY. */
    XCVR_RSM_TRIG_TX_DIG_EN     = 3U,  /*!<  Trigger the RSM module upon TX digital enable from TSM. */
    XCVR_RSM_TRIG_SEQ_SPARE3    = 4U,  /*!<  Trigger the RSM module upon seq_spare3 assertion from TSM. */
    XCVR_RSM_TRIG_PAT_MATCH     = 5U,   /*!<  Trigger the RSM module upon pattern match detection from the localization module. */
    XCVR_RSM_TRIG_INVALID /* Must always be last! */
}   XCVR_RSM_TRIG_T;

/*! @brief  RSM Calibration Configuration. Selects the calibrations to include in RSM TX and RX sequences. */
typedef enum
{
    XCVR_RSM_TSM_DEFAULT        = 0U, /*!< Configure TSM settings programming to default settings */
    XCVR_RSM_TSM_FULL_CAL       = 1U, /*!<  Configure TSM settings programming to full calibration: perform HPM and RCCAL and DCOC cal in both RX and TX warmups for RSM (Requires T_FC=150usec!) */
    XCVR_RSM_TSM_PART_CAL       = 2U,  /*!<  ConfigureTSM settings programming to  assert seq_lo_pup_vlo_rx/tx in both TX and RX, and to enable HPM in RX (use for faster T_FC cases) */
    XCVR_RSM_CAL_MODE_INVALID /* Must always be last! */
}   XCVR_RSM_TSM_CAL_MODE_T;

/*! @brief  RSM HPM Calibration Configuration. Selects the HPM calibrations time to include in RSM TX and RX sequences. */
typedef enum
{
    XCVR_RSM_TSM_HPM_CAL_BYP        = 0U, /*!< Configure TSM settings programming to bypass HPM cal  (used only if HPM CAL is completely skipped) */
    XCVR_RSM_TSM_HPM_52US_CAL       = 1U, /*!<  Configure TSM settings programming to 52usec HPM cal (default value, almost always used) */
    XCVR_RSM_TSM_HPM_102US_CAL      = 2U,  /*!<  ConfigureTSM settings programming to 102usec HPM cal (require PLL settings as well to go with this value). */
    XCVR_RSM_cAL_TIME_INVALID /* Must always be last! */
}   XCVR_RSM_TSM_HPM_CAL_TIME_T;

/*! @brief  RSM SQTE RATE settings. */
typedef enum
{
    XCVR_RSM_RATE_1MBPS       = 0U, /*!< RSM rate of 1Mbps. Must match how XCVR is configured! */
    XCVR_RSM_RATE_2MBPS       = 1U,  /*!<  RSM rate of 2Mbps. Must match how XCVR is configured! */
    XCVR_RSM_RATE_INVALID /* Must always be last! */
}   XCVR_RSM_SQTE_RATE_T;

#if defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1)
/*! @brief  RSM SQTE PN length. */
typedef enum
{
    XCVR_RSM_SQTE_PN32       = 0U, /*!< A 32 bit PN sequence is used in SQTE packets. THis setting is programmed in the PHY.  */
    XCVR_RSM_SQTE_PN64       = 1U,  /*!< A 64 bit PN sequence is used in SQTE packets. THis setting is programmed in the PHY. */
    XCVR_RSM_RTT_LEN_INVALID /* Must always be last! */
}   XCVR_RSM_SQTE_RTT_LEN_T;
#endif /* defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1) */

/*! @brief RXDIG IQ/Phase averaging window enumeration type. */
/* Must match the birfield programming for RX_IQ_PH_AVG_WIN in XCVR_RXDIG->CTRL1 regsiter */
typedef enum
{
    XCVR_RSM_AVG_WIN_DISABLED    = 0U, /*!< No IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_4_SMPL      = 1U, /*!< 4 sample IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_8_SMPL      = 2U, /*!< 8 sample IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_16_SMPL     = 3U, /*!< 16 sample IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_32_SMPL     = 4U, /*!< 32 sample IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_64_SMPL     = 5U, /*!< 64 sample IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_128_SMPL    = 6U, /*!< 128 sample IQ/Phase averaging performed */
    XCVR_RSM_AVG_WIN_256_SMPL    = 7U, /*!< 256 sample IQ/Phase averaging performed */
}   XCVR_RSM_AVG_WIN_LEN_T;


/* Define callback function for RSM interrupt. */
/*! *********************************************************************************
* \brief  This callback is a pointer to a user routine to be called when RSM interrtupt happens.
*
*  This function is the user callback for DSB interrupts.
*
* \param[in] userData - pointer to user data to be passed to the callback function
* \param[in] abort - boolean indicating if an abort flag was asserted.
* \param[in] rsm_csr - the contents of the RSM Control and Status register for identifying interrupt type.
*
* \note This callback is called for any RSM interrupt, whether an abort flag was raised, an intermediate interrupt was triggered,
* or the end-of-sequence interrupt was asserted.
***********************************************************************************/
typedef void (*rsm_int_callback)(void *userData, bool abort, uint32_t rsm_csr);


/*! @brief RSM main configuration structure. This structure covers common configurations and some PDE configurations. A child structure contains SQTE only configurations. */
typedef struct
{
    XCVR_RSM_MODE_T op_mode;                 /*!< Operating mode for the RSM */
    uint8_t num_steps;                       /*!< Number of steps for the RSM sequence, including FCS for the SQTE case. Max is 128 but the PN sequence storage may also limit the number of steps. A value of 0 is not valid. */
    uint8_t t_fc;                            /*!< T_FC timing value in usec */
    uint8_t t_ip1;                           /*!< T_IP1 timing value in usec */
    uint8_t t_ip2;                           /*!< T_IP2 timing value in usec */
    uint16_t t_pm0;                           /*!< T_PM0 timing value in usec. The T_PM1 field will be set to T_PM0+10. Valid range is 10usec to 630usec (accounting for T_PM1 will be 10 usec longer). This value represents the entire T_PM period, covering one or more antenna slots and also any required tone extension slot. */

    uint8_t rxdig_dly;                       /*!< Used in longer sequences to optimize enable of the RX digital. Can cause a problem in warmup if this is incorrect. Compensating for first T_FC per the standard since RSM triggers on TSM warmup. */
    uint8_t txdig_dly;                       /*!< Used in longer sequences to optimize enable of the TX digital. Can cause a problem in warmup if this is incorrect. Compensating for first T_FC per the standard since RSM triggers on TSM warmup. */
    XCVR_RSM_TRIG_T trig_sel;                /*!< Selects the trigger mode for the RSM module. */
    uint16_t trig_delay;                     /*!< Max value = 2047. SQTE mode: delay from trigger to when rx_en or tx_en is asserted. PDE mode: delay from trigger to when the first rx2tx or tx2rx occurs. */
    uint8_t num_ant_path;                    /*!< Number of antenna paths, must range from 1 to 4. */
    rsm_int_callback user_callback;          /*!< User defined callback to be called to handle interrupts. */
#if defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1)
    XCVR_RSM_SQTE_RTT_LEN_T rtt_len;         /*!< SQTE ONLY: Choose the length of PN packets used in SQTE packet exchanges.  */
#endif /* defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1) */
    XCVR_RSM_SQTE_RATE_T rate;               /*!< SQTE ONLY: Indicates to the RSM the data rate being used by the XCVR. Must match the XCVR configuration.  */
    XCVR_RSM_AVG_WIN_LEN_T averaging_win;   /*!< The number of IQ or phase samples to average in RXDIG to produce one output sample. */
    bool use_rsm_dma_mask;                  /*!< Selects to use the RSM DMA mask signal rather than the LCL DMA mask. Only valid when 1 antenna is used. */
    uint8_t rsm_dma_dly_pm;                 /*!< DMA delay from end of RX warmup to assertion of DMA mask signal in usec. Applies to PM_RX state only. RSM_DMA_DLY field. */
    uint8_t rsm_dma_dly_fm_ext;             /*!< DMA delay from end of RX warmup to assertion of DMA mask signal in usec. Applies to FM_RX or EXT_RX states only. RSM_DMA_DLY0 field. Active even if RSM is not providing the DMA mask for PM states.*/
    uint16_t rsm_dma_dur_pm;                /*!< DMA mask duration in usec. Applies to PM_RX state only. RSM_DMA_DUR field. */
    uint16_t rsm_dma_dur_fm_ext;            /*!< DMA mask duration in usec. Applies to FM_RX or EXT_RX states only. RSM_DMA_DUR0 field. Active even if RSM is not providing the DMA mask for PM states. */
} xcvr_lcl_rsm_config_t;

/*! @brief RSM Frequency Step configuration structure. */
typedef struct
{
    uint8_t ext_channel_num_ovrd_lsb;            /*!< Channel number override LSB for this Frequency Step */
    uint8_t ext_channel_num_ovrd_msb;            /*!< Channel number override LSB for this Frequency Step */
    uint8_t ext_ctune;                           /*!< CTUNE factor for this Frequency Step */
    uint8_t ext_hmp_cal_factor_lsb;              /*!< HPM_CAL factor LSB for this Frequency Step */
    uint8_t tpm_step_format_hmp_cal_factor_msb;  /*!< Mixed field with T_PM_SEL, STEP_FORMAT, and HPM_CAL factor MSB for this Frequency Step */
} xcvr_lcl_fstep_t;

/*! @brief RSM HPM CAL interpolation structure. */
typedef struct
{
    uint16_t hpm_cal_factor_2442;   /*!< HPM_CAL_FACTOR used to calculate Kcal_2442, used in other algorithms */
    uint16_t eff_cal_freq;          /*!< The effective frequency for the HPM cal, based on COUNT1 and COUNT2 values. Used in other algorithms */    
} xcvr_lcl_hpm_cal_interp_t;

/* Bitfield access macros for the uint8_t elements in the xcvr_lcl_fstep_t structure */
/*! @brief  RSM Step Format enumeration type. */
typedef enum
{
    XCVR_RSM_STEP_FCS           = 0U,  /*!< Frequency Check Sequence step type */
    XCVR_RSM_STEP_PK_PK         = 1U,  /*!<  Pk-Pk step type */
    XCVR_RSM_STEP_TN_TN         = 2U,  /*!<  Tn-Tn step type */
    XCVR_RSM_STEP_PK_TN_TN_PK   = 3U   /*!<  Pk-Tn-Tn-Pk step type */
}   XCVR_RSM_FSTEP_TYPE_T;

/*! @brief  RSM T_PM & T_FM selection enumeration type. */
typedef enum
{
    XCVR_RSM_T_PM0_SEL           = 0U, /*!< T_PM0 selected */
    XCVR_RSM_T_PM1_SEL           = 1U, /*!< T_PM1 selected */
    XCVR_RSM_T_PM2_SEL           = 2U, /*!< T_PM2 selected */
    XCVR_RSM_T_PM3_SEL           = 3U, /*!< T_PM3 selected */
    XCVR_RSM_T_FM0_SEL           = 0U, /*!< T_FM0 selected (when step is FCS type) */
    XCVR_RSM_T_FM1_SEL           = 1U, /*!< T_FM0 selected (when step is FCS type) */
}   XCVR_RSM_T_PM_FM_SEL_T;

/* Fstep defines */
#define XCVR_RSM_HPM_CAL_MSB_MASK   (0xFU)
#define XCVR_RSM_HPM_CAL_MSB_SHIFT  (0U)
#define XCVR_RSM_HPM_CAL_MSB(x)     (((uint8_t)(((uint8_t)(x)) << XCVR_RSM_HPM_CAL_MSB_SHIFT)) & XCVR_RSM_HPM_CAL_MSB_MASK)
#define XCVR_RSM_STEP_FORMAT_MASK   (0x30U)
#define XCVR_RSM_STEP_FORMAT_SHIFT  (4U)
#define XCVR_RSM_STEP_FORMAT(x)     (((uint8_t)(((uint8_t)(x)) << XCVR_RSM_STEP_FORMAT_SHIFT)) & XCVR_RSM_STEP_FORMAT_MASK)
#define XCVR_RSM_T_PM_FM_SEL_MASK   (0xC0U)
#define XCVR_RSM_T_PM_FM_SEL_SHIFT  (6U)
#define XCVR_RSM_T_PM_FM_SEL(x)     (((uint8_t)(((uint8_t)(x)) << XCVR_RSM_T_PM_FM_SEL_SHIFT)) & XCVR_RSM_T_PM_FM_SEL_MASK)
/* RTT defines; All should be applied to the 4 octets of RTT data assembled to a uint32_t */
#define XCVR_RSM_RTT_VALID_MASK         (0x00000001U)
#define XCVR_RSM_RTT_VALID_SHIFT        (0U)
#define XCVR_RSM_RTT_FOUND_MASK         (0x00000002U)
#define XCVR_RSM_RTT_FOUND_SHIFT        (1U)
#define XCVR_RSM_RTT_CFO_MASK           (0x0003FFFCU)
#define XCVR_RSM_RTT_CFO_SHIFT          (2U)
#define XCVR_RSM_RTT_INT_ADJ_MASK       (0x000C0000U)
#define XCVR_RSM_RTT_INT_ADJ_SHIFT      (18U)
#define XCVR_RSM_RTT_HAM_DIST_SAT_MASK  (0x00300000U)
#define XCVR_RSM_RTT_HAM_DIST_SAT_SHIFT (20U)
#define XCVR_RSM_RTT_P_DELTA_MASK       (0xFFC00000U)
#define XCVR_RSM_RTT_P_DELTA_SHIFT      (22U)

#define BACKUP_LCL_REGS                 (0)             /*!< Select whether to include backup/restore of XCVR_MISC LCL registers or not */

/*! @brief PN short configuration storage structure. */
typedef struct
{
    uint32_t init_to_reflect_pn;                                /*!< PN for Initiator-to-Reflector packet */
    uint32_t reflect_to_init_pn;                                /*!< PN for Reflector-to-Initiator packet */
} xcvr_lcl_pn32_config_t;

/*! @brief PN long configuration storage structure. */
typedef struct
{
    uint32_t init_to_reflect_pn_lsb;                                /*!< PN for Initiator-to-Reflector packet least significant portion */
    uint32_t init_to_reflect_pn_msb;                                /*!< PN for Initiator-to-Reflector packet most significant portion */
    uint32_t reflect_to_init_pn_lsb;                                /*!< PN for Reflector-to-Initiator packet least significant portion */
    uint32_t reflect_to_init_pn_msb;                                /*!< PN for Reflector-to-Initiator packet most significant portion */
} xcvr_lcl_pn64_config_t;

/*! @brief Round Trip Time rawresults structure (data is packed together). */
typedef struct
{
    uint8_t rtt_data_b0_success;                                   /*!< LSB (7 bits of byte 0) of RTT data plus success bit in bit 0 */
    uint8_t rtt_data_b1;                                           /*!< Byte 1, next 8 bits of RTT data  */
    uint8_t rtt_data_b2;                                           /*!< Byte 2, next 8 bits of RTT data  */
    uint8_t rtt_data_b3;                                           /*!< Byte 3, next 8 bits of RTT data  */
} xcvr_lcl_rtt_data_raw_t;

/*! @brief Round Trip Time unpacked results structure  */
typedef struct
{
    bool rtt_vld;                                                   /*!<  */
    bool rtt_found;                                                 /*!< HARTT operation is done and a valid PN pattern was detected */
    int32_t cfo;                                                   /*!< The high accuracy CFO computed by the HARTT block through the CORDIC algorithm. Signed, reported in Hz. */
    uint8_t int_adj;                                                /*!< An integer adjustment of the timing which takes a value different of 0 when the early-late mechanism in the HARTT block chooses a peak different of the one chosen in the acquisition module (possible values are {-1,0,+1}).  */
    uint8_t ham_dist_sat;                                           /*!<  Computed Hamming distance saturated to 2 bits, format is ufix2.*/
    uint16_t p_delta;                                               /*!<  Difference between the squared correlation magnitude values, pm-pp provided by the HARTT block, format is sfix10En9.*/
} xcvr_lcl_rtt_data_t;

/*! @brief PLL Calibration results storage for HPM CAL. */
typedef struct 
{
    uint16_t hpm_cal_val;                                           /*!< External HPM CAL value is uint16_t. */
#if (defined(CTUNE_MANUAL_CAL) && (CTUNE_MANUAL_CAL == 1))
    uint8_t ctune_cal_val;                                          /*!< External CTUNE value is uint8_t. */
#endif /* (defined(CTUNE_MANUAL_CAL) && (CTUNE_MANUAL_CAL == 1)) */
} xcvr_lcl_pll_cal_data_t;                               

/*! @brief Channel number type to specify frequency (according to the setting of the PLL's CHAN_MAP[HOP_TBL_CFG_OVRD] bitfield). */
typedef uint16_t channel_num_t;


/* RSM-related register backup structure. Stores registers that must be changed in different peripherals for RSM to work. */
typedef struct
{
    /* XCVR_MISC */
#if BACKUP_LCL_REGS
    uint32_t XCVR_MISC_DMA_CTRL;
    uint32_t XCVR_MISC_LCL_CFG0;
    uint32_t XCVR_MISC_LCL_CFG1;
    uint32_t XCVR_MISC_LCL_TX_CFG0;
    uint32_t XCVR_MISC_LCL_TX_CFG1;
    uint32_t XCVR_MISC_LCL_TX_CFG2;
    uint32_t XCVR_MISC_LCL_RX_CFG0;
    uint32_t XCVR_MISC_LCL_RX_CFG1;
    uint32_t XCVR_MISC_LCL_RX_CFG2;
    uint32_t XCVR_MISC_LCL_PM_MSB;
    uint32_t XCVR_MISC_LCL_PM_LSB;
    uint32_t XCVR_MISC_LCL_GPIO_CTRL0;
    uint32_t XCVR_MISC_LCL_GPIO_CTRL1;
    uint32_t XCVR_MISC_LCL_GPIO_CTRL2;
    uint32_t XCVR_MISC_LCL_GPIO_CTRL3;
    uint32_t XCVR_MISC_LCL_GPIO_CTRL4;
    uint32_t XCVR_MISC_LCL_DMA_MASK_DELAY;
    uint32_t XCVR_MISC_LCL_DMA_MASK_PERIOD;
    uint32_t XCVR_MISC_RSM_CTRL0;
    uint32_t XCVR_MISC_RSM_CTRL1;
    uint32_t XCVR_MISC_RSM_CTRL2;
    uint32_t XCVR_MISC_RSM_CTRL3;
    uint32_t XCVR_MISC_RSM_CTRL4;
#endif /* BACKUP_LCL_REGS */
    /* XCVR_2P4GHZ_PHY */
    uint32_t XCVR_2P4GHZ_PHY_RTT_CTRL;
    uint32_t XCVR_2P4GHZ_PHY_RTT_REF;
    /* XCVR_TXDIG */
    uint32_t XCVR_TX_DIG_DATA_PADDING_CTRL;
    uint32_t XCVR_TX_DIG_DATA_PADDING_CTRL1;
    uint32_t XCVR_TX_DIG_PA_CTRL;
    /* XCVR_PLL */
    uint32_t XCVR_PLL_DIG_CHAN_MAP;
    uint32_t XCVR_PLL_DIG_HPM_BUMP;
    uint32_t XCVR_PLL_DIG_HPM_CTRL;
    uint32_t XCVR_PLL_DIG_LPM_CTRL;
    uint32_t XCVR_PLL_DIG_DELAY_MATCH;
    uint32_t XCVR_PLL_DIG_HPM_SDM_RES;
    uint32_t XCVR_PLL_DIG_MOD_CTRL;
    uint32_t XCVR_TX_DIG_GFSK_CTRL;
    uint32_t XCVR_PLL_DIG_PLL_NUM_OFFSET;
    uint32_t XCVR_PLL_DIG_TUNING_CAP_TX_CTRL;
    uint32_t XCVR_PLL_DIG_TUNING_CAP_RX_CTRL;
    /* XCVR_TSM (used in PLL overrides) */
    uint32_t XCVR_TSM_OVRD2;
    uint32_t XCVR_TSM_OVRD3;
    /* XCVR_RXDIG */
    uint32_t XCVR_RX_DIG_RCCAL_CTRL1;
    uint32_t XCVR_RX_DIG_DFT_CTRL;
    uint32_t XCVR_RX_DIG_DMA_CTRL;
    uint32_t XCVR_RX_DIG_CTRL1;
    /* RADIO_CTRL */
    uint32_t RADIO_CTRL_RF_CTRL;
} rsm_reg_backup_t;

typedef uint32_t tsm_u32_backup_array_t[NUM_TSM_U32_REGISTERS]; /*!< Backup array of uint32_t to store entire TSM register set. */

/* RSM interrupts are only supported on the NBU CPU */
#if defined(KW45B41Z82_NBU_SERIES) || defined(KW45B41Z83_NBU_SERIES)
/*! @brief Define callback function pointer type for RSM interrupt.
 *
 * This callback function is called in the RSM interrupt handle.
 *
 * @param userData Data available from callback.
 *
 * @note This function pointer type is only available for the NBU CPU as the CM33 CPU does not have connection to RSM interrupt line
 */
typedef void (*rsm_sw_callback)(void *userData, bool abort_flag, uint32_t CSRval);

/*! @brief RSM handler structure*/
typedef struct
{
    rsm_sw_callback user_callback; /*!< Callback function */
    void *userData;                /*!< User data available from callback */
} rsm_sw_handler_t;

/*! @brief RSM IRQ enable/disable masks; Intended to be OR'd together to enable or disable multiple interrupts at a time. */
#define  XCVR_LCL_RSM_IRQ_EN_ALL_BITS  (XCVR_MISC_RSM_CSR_RSM_IRQ_IP1_EN_MASK | XCVR_MISC_RSM_CSR_RSM_IRQ_IP2_EN_MASK | \
                                XCVR_MISC_RSM_CSR_RSM_IRQ_FC_EN_MASK | XCVR_MISC_RSM_CSR_RSM_IRQ_EOS_EN_MASK | \
                                XCVR_MISC_RSM_CSR_RSM_IRQ_ABORT_EN_MASK) /* all of the interrupt ENABLE bits. Useful also in creating an error check mask */
#define  XCVR_LCL_RSM_IRQ_STAT_ALL_BITS (XCVR_MISC_RSM_CSR_RSM_IRQ_IP1_MASK | XCVR_MISC_RSM_CSR_RSM_IRQ_IP2_MASK | \
                                XCVR_MISC_RSM_CSR_RSM_IRQ_FC_MASK | XCVR_MISC_RSM_CSR_RSM_IRQ_EOS_MASK | \
                                XCVR_MISC_RSM_CSR_RSM_IRQ_ABORT_MASK) /* all of the interrupt STATUS bits. Useful also in creating an error check mask */

#endif /* defined(KW45B41Z82_NBU_SERIES) || defined(KW45B41Z83_NBU_SERIES)) */

extern xcvr_lcl_hpm_cal_interp_t hpm_cal_2442_data;

/*******************************************************************************
 * API
 ******************************************************************************/
#ifdef GCOV_DO_COVERAGE /* local except when testing code coverage */
xcvrLclStatus_t XCVR_LCL_RsmCheckSeqLen(uint16_t length, uint16_t maxlen);
bool XCVR_LCL_RsmCheckDmaDuration(uint16_t dma_duration, XCVR_RSM_SQTE_RATE_T rate, XCVR_RSM_AVG_WIN_LEN_T avg_win);
xcvrLclStatus_t XCVR_LCL_RsmCheckDmaMask(const xcvr_lcl_rsm_config_t * rsm_settings_ptr, xcvrLclStatus_t status_in);
#endif /* !defined(GCOV_DO_COVERAGE) */


#if defined(KW45B41Z82_NBU_SERIES) || defined(KW45B41Z83_NBU_SERIES)   /* RSM interrupts are only supported on the NBU CPU */
/*!
 * @brief Register a callback from upper layers for the RSM interrupt.
 *
 * This function registers a callback from the upper layers for the radio to call when RSM interrupt occurs.
 *
 * @param[in] fptr  The function pointer to a RSM callback.
 *
 * @note This function is only available for the NBU CPU as the CM33 CPU does not have connection to RSM interrupt line
 */
void XCVR_LCL_RsmRegisterCb (const rsm_sw_handler_t * user_rsm_handler); /* allow upper layers to provide RSM callback */


/*!
 * @brief Enable or disable the RSM interrupts.
 *
 * This function allows individually enabling and disabling the RSM interrupts.
 *
 * @param[in] mask  The OR'd mask of multiple interrupts to enable or disable. The mask must use the RSM CSR enable bits in their proper position from the register header file.
 * @param[in] irq_enabled  True == the interrupt will be enabled, false == the interrupt will be disabled.
 *
 * @note This function is only available for the NBU CPU as the CM33 CPU does not have connection to RSM interrupt line
 */
bool XCVR_LCL_RsmIrqEnDis (uint32_t mask, bool irq_enabled);

#endif /* defined(KW45B41Z82_NBU_SERIES) || defined(KW45B41Z83_NBU_SERIES)) */


/*!
 * @brief Function to validate the settings structure for Ranging State Machine prior to calling initialization.
 *
 * This function validates the Ranging State Machine (RSM) initialization settings structure. It is implemented as a separate function in order to simplify the init
 * routine and also to allow for validation ahead of time in case the init routine is in a critical timing path.
 *
 * @param rsm_settings_ptr the pointer to a settings structure for RSM initialization.
 * 
 * @return The status of the validation.
 * 
 */
xcvrLclStatus_t XCVR_LCL_ValidateRsmSettings(const xcvr_lcl_rsm_config_t * rsm_settings_ptr);

/*!
 * @brief Function to initialize the PLL for RSM ranging operation.
 *
 * This function initializes any customized PLL settings for RSM operaiton. It is intended to be used to as a helper for both ::XCVR_LCL_RsmInit() and for
 * ::XCVR_LCL_CalibratePll() to put the PLL in proper configuration before RSM operations.
 *
 * @param rate the data rate to be used in RSM operation.
 * 
 * @return The status of the init process.
 * 
 * @note This routine modifies a number of registers which must be saved and then restored before changing back to normal operation. The ::XCVR_LCL_RsmDeInit() function
 * is intended to return to the prior settings at the end of RSM operation. If interim restoration is needed then ::XCVR_LCL_RsmPLLBackup() and ::XCVR_LCL_RsmPLLRestore() can be used.
 */
 void XCVR_LCL_RsmPLLInit(XCVR_RSM_SQTE_RATE_T rate);

/*!
 * @brief Function to backup  the PLL settings modified by XCVR_LCL_RsmPLLInit.
 *
 * This function backs up the contents of PLL regsiters before the customized PLL settings for RSM operation. 
 *
 * @param reg_backup_ptr the pointer to a settings structure for register backup.
 * 
 * @note This routine backs up the registers modified by ::XCVR_LCL_RsmPLLInit().
 */
xcvrLclStatus_t XCVR_LCL_RsmPLLBackup(rsm_reg_backup_t * reg_backup_ptr);

/*!
 * @brief Function to restore the PLL to prior settings after overrides are no longer needed.
 *
 * This function restores prior settings after any customized PLL settings for RSM operaiton. 
 * 
 * @param reg_backup_ptr the pointer to a settings structure for register restore.
 * 
 * @note This routine restores the registers modified by ::XCVR_LCL_RsmPLLInit().
 */
xcvrLclStatus_t XCVR_LCL_RsmPLLRestore(const rsm_reg_backup_t * reg_backup_ptr);

/*!
 * @brief Function to initialize support for Ranging State Machine.
 *
 * This function initializes the Ranging State Machine (RSM), TSM, TX_DIG, GEN4PHY, and other registers before TX or RX operations using the RSM module.
 * This function calls helper functions to implement some of the TSM timing 
 *
 * @param rsm_settings_ptr the pointer to a settings structure for RSM initialization.
 * 
 * @return The status of the init process.
 * 
 * @note This routine modifies a number of registers which must be restored before changing back to normal operation. The ::XCVR_LCL_RsmDeInit() function
 * is intended to return to the prior settings.
 */
xcvrLclStatus_t XCVR_LCL_RsmInit(const xcvr_lcl_rsm_config_t * rsm_settings_ptr);


/*!
 * @brief Function to de-initialize support for Ranging State Machine.
 *
 * This function resets the registers touched by ::XCVR_LCL_RsmInit() to allow the radio to return to normal operating modes. After this routine
 * is called, the RSM will be disabled and the TSM, TX_DIG, GEN4PHY will all be returned to prior settings.
 *
 */
void XCVR_LCL_RsmDeInit(void);

/*!
 * @brief Function to cleanly stop completed or abort ongoing Ranging State Machine operations.
 *
 * @param abort Selects whether this is a stop or abort request. True == abort, False == stop.
 *
 * This function aborts any ongoing RSM operations prior to the normal end of sequence. It is also used to stop the RSM after normal completion
 * of a RSM sequence. 
 *
 * @note This routine performs a wait for the RSM state machine to return to IDLE state to ensure it is safe to clear the abort bit or clear RX or TX enables.
 * @note This routine must be called every time that RSM is started via ::XCVR_LCL_RsmGo() as it restores registers that are reprogrammed by the 
 * ::XCVR_LCL_RsmGo() routine to support the RSM. Failure to this will cause the normal Bluetooth or GENFSK radio operations to malfunction.
 */
void XCVR_LCL_RsmStopAbort(bool abort);

/*!
 * @brief Function to start the Ranging State Machine.
 *
 * This function starts the RSM in the desired (RX or TX) role. If the RSM has a hardware trigger selected then the RSM will start upon the assertion of that trigger. If the RSM has a 
 * software trigger selected then the RSM will start immediately. For both hardware and software triggers, the RSM_TRIG_DLY will control the time delay to the actual start of the RSM sequence.
 *
 * @param role Role for the RSM, Initiator/Reflector or PD/MD, depending on op_mode setting.
 * @param rsm_settings_ptr the pointer to a settings structure for RSM initialization.
 *
 * @return The status of the init process.
 * 
 * @pre The RSM must be initialized, TSM reconfigured, and all RAM based tables programmed before calling this routine.
 *
 * @note Every RSM sequence that is started must be either aborted or stopped in order to prevent unexpected executions of the RSM sequence due to hardware triggers. The function
 * ::XCVR_LCL_RsmStopAbort() must be used to perform the stop or abort (as needed) for every execution of the go routine.
 */
xcvrLclStatus_t XCVR_LCL_RsmGo(XCVR_RSM_RXTX_MODE_T role, const xcvr_lcl_rsm_config_t * rsm_settings_ptr);

/*!
 * @brief Function to snapshot the TSM timing registers to a storage structure.
 *
 * This function captures the state of the TSM timing registers and is used both before and after calling ::XCVR_LCL_RsmInit(). When
 * called before, it stores the state of the TSM for normal operation. When called after, it stores the state of the TSM for RSM operations.
 * Both cases are intended to allow for later restore of a specific set of TSM timings without performing additional calculations.
 *
 * @param curr_tsm_timings the for storage of the TSM timing values read from hardware registers.
 *
 * @return The status of the TSM timings read process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_GetTsmTimings(uint32_t curr_tsm_timings[]);

/*!
 * @brief Function to apply the new (pre-calculated) TSM timing values for RSM operations.
 *
 * This function updates a subset of new TSM timing register values for specific RSM operations. The input structure is the relevant  
 *  TSM register changes only. 
 *
 * @param new_tsm_timings the pointer to a structure for output of TSM timing values.
 *
 * @return The status of the TSM timings update process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_ReprogramTsmTimings(const xcvr_lcl_tsm_config_t * new_tsm_timings);

/*!
 * @brief Function to restore the TSM timing registers from a storage structure.
 *
 * This function restores the state of the TSM timing registers and is used to restore the state of the TSM registers.
 * It can be used to restore of a specific set of TSM timings without performing additional calculations for either entering or leaving RSM modes.
 *
 * @param curr_tsm_timings the array to read for TSM timing values to configure in the hardware registers.
 *
 * @return The status of the TSM timings restore process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_SetTsmTimings(const uint32_t curr_tsm_timings[]);

/*!
 * @brief Function to compute FAST Start rx and tx jump point to achieve desired T_FC/T_IP.
 *
 * This function write the TSM FAST control register to skip a part of the WU sequence depending on the rsm role
 * to achieve T_FC and T_IP timing. The TSM is not compatible with independant T_IP1 and T_IP2, so min(T_IP1, T_IP2)
 * is programmed.
 *
 * @param role The RSM role ( inititor or reflector ).
 * @param t_fc T_FC timing in us
 * @param t_ip1 T_IP1 timing in us
 * @param t_ip2 T_IP2 timing in us
 *
 * @return The status of the function (xcvrLclStatus_t).
 * 
 */
xcvrLclStatus_t XCVR_LCL_Set_TSM_FastStart( XCVR_RSM_RXTX_MODE_T role, uint8_t t_fc, uint8_t t_ip1, uint8_t t_ip2);

/*!
 * @brief Function to backup the state of various XCVR registers changed by RSM init.
 *
 * This function backs up registers in multiple XCVR blocks to store their state before or during RSM operations for
 * later restoration.
 *
 * @param reg_backup_ptr the pointer to a settings structure for register backup.
 * 
 * @return The status of the backup.
 * 
 */
xcvrLclStatus_t XCVR_LCL_RsmRegBackup(rsm_reg_backup_t * reg_backup_ptr);

/*!
 * @brief Function to restore the state of various XCVR registers changed by RSM init.
 *
 * This function restores registers to multiple XCVR blocks to replace their state to what it was before or during RSM operations 
 *
 * @param reg_backup_ptr the pointer to a settings structure for register restore.
 * 
 * @return The status of the restore.
 * 
 */
xcvrLclStatus_t XCVR_LCL_RsmRegRestore(const rsm_reg_backup_t * reg_backup_ptr);

/*!
 * @brief Function to program the Frequency Step structure in Packet RAM for RSM operations.
 *
 * This function programs the Frequency Step structure with the frequency value, CTUNE value, HPM cal value
 * T_PM setting and step format for each frequency step in a RSM sequence.
 *
 * @param fstep_settings the pointer to a structure for frequency step programming, assumed to be an array.
 * @param num_steps the number of frequency steps to program.
 *
 * @return The status of the frequency step programming process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_SetFstepRam(const xcvr_lcl_fstep_t * fstep_settings, uint16_t num_steps);

/*!
 * @brief Function to program the Short PseudoNoise structure in Packet RAM for RSM operations.
 *
 * This function programs the short pseudonoise structure with Initiator and Reflector 32-bit values.
 *
 * @param pn_values the pointer to a structure for frequency step programming, assumed to be an array.
 * @param num_steps the number of pseudonoise steps to program.
 *
 * @return The status of the pseudonoise step programming process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_SetPnRamShort(const xcvr_lcl_pn32_config_t * pn_values, uint16_t num_steps);

#if defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1)
/*!
 * @brief Function to program the Long PseudoNoise structure in Packet RAM for RSM operations.
 *
 * This function programs the short pseudonoise structure with Initiator and Reflector 64-bit values.
 *
 * @param pn_values the pointer to a structure for pseudonoise step programming, assumed to be an array.
 * @param num_steps the number of pseudonoise steps to program.
 *
 * @return The status of the pseudonoise step programming process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_SetPnRamLong(const xcvr_lcl_pn64_config_t * pn_values, uint16_t num_steps);
#endif /* defined(SUPPORT_RSM_LONG_PN) && (SUPPORT_RSM_LONG_PN == 1) */

/*!
 * @brief Function to read the CTUNE_BEST_DIFF values from Packet RAM for RSM operations.
 *
 * This function reads the CTUNE_BEST_DIFF values from Packet RAM to be used for tuning .
 *
 * @param ctune_results the pointer to an array of uint8_t to store CTUNE_BEST_DIFF values.
 * @param num_steps the number of CTUNE_BEST_DIFF values to read.
 *
 * @return The status of the CTUNE_BEST_DIFF values read process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_GetCtuneResults(uint8_t * ctune_results, uint16_t num_steps);

/*!
 * @brief Function to unpack Round Trip Time data structures read from Packet RAM for RSM operations.
 *
 * This function unpacks the raw data structure that was read from RTT Packet RAM and places the data into a formatted structure.
 *
 * @param rtt_results the packed RTT results data read from Packet RAM.
 * @param rtt_unpacked the structure to contain the unpacked RTT data.
 * @param rate the data rate for the captured RTT packet, for conversion to Hz of the CFO.
 *
 * @return The status of the CTUNE_BEST_DIFF values read process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_UnpackRttResult(const xcvr_lcl_rtt_data_raw_t * rtt_results, xcvr_lcl_rtt_data_t * rtt_unpacked, XCVR_RSM_SQTE_RATE_T rate);

/*!
 * @brief Function to read the Round Trip Time values from Packet RAM for RSM operations.
 *
 * This function reads the Round Trip Time values from Packet RAM to be used for calculating distance..
 *
 * @param rtt_results the pointer to an array of structures to store Round Trip Time values in raw format.
 * @param num_steps the number of Round Trip Time values to read.
 *
 * @return The status of the Round Trip Time values read process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_GetRttResults(xcvr_lcl_rtt_data_raw_t * rtt_results, uint16_t num_steps);

/*!
 * @brief Function to format the input parameters into a single Fstep structure.
 *
 * This formats the channel number, CTUNE data, HPM CAL factor, step format and T_PM_SEL values into the Fstep structure.
 *
 * @param fstep_entry the pointer to a structure for frequency step programming.
 * @param channel_num the channel number to be applied.
 * @param ctune the ctune value to be applied.
 * @param hpm_cal the HPM CAL value to be applied.
 * @param step_format the step format to be applied.
 * @param t_pm_sel the T_PM timing selection to be applied.
 *
 * @return The status of the function, success or error.
 * 
 */
xcvrLclStatus_t XCVR_LCL_MakeFstep(xcvr_lcl_fstep_t * fstep_entry, 
                                        uint16_t channel_num, 
                                        uint8_t ctune, 
                                        uint16_t hpm_cal, 
                                        XCVR_RSM_FSTEP_TYPE_T step_format, 
                                        XCVR_RSM_T_PM_FM_SEL_T t_pm_sel);


/*!
 * @brief Function to perform PLL calibrations to capture CTUNE and HPM data for later use.
 *
 * This function performs a number of RX warmups at a list of frequencies in order to calibrate the PLL and
 * capture the CTUNE and HPM calibrations for later use. Any number of frequencies is supported. 
 * This routine has multiple usage scenarios, such as brute force calibration at every target frequency or alternatively
 * calibration at a smaller number of points to feed an interpolation algorithm for faster generation of cal values.
 * Both the CTUNE and HPM calibration values are captured during this process.
 *
 * @param freq_list the pointer to an array of frequencies to tune to and capture calibration values. This must follow the format
 * defined in the PLL's CHAN_MAP[HOP_TBL_CFG_OVRD] bitfield and match the current setting of the field. Frequency values need not be sorted.
 * @param cal_results the pointer to an array of structures to store the calibration results in raw format.
 * @param num_freqs the number of frequencies at which calibration should be performed.
 * @param update_curve_fit selects for updating the curve fit data storage when the calibration frequency is 2442MHz. Error is triggered if 2442MHz is not in the frequency list.
 * @param rate the data rate to be used in RSM operation.
 *
 * @return The status of the PLL calibration process.
 *
 */
xcvrLclStatus_t XCVR_LCL_CalibratePll(const channel_num_t * freq_list, xcvr_lcl_pll_cal_data_t * cal_results, uint16_t num_freqs, bool update_curve_fit, XCVR_RSM_SQTE_RATE_T rate);

/*!
 * @brief Function to calculate interpolated values for HPM CAL based on previously calculated equations for approximations.
 *
 * This function calculates interpolated values for HPM CAL values at different frequencies based on data captured in the XCVR_LCL_CalibratePll() routine when the update_curve_fit
 * parameter is set to true. These equations are generated from a single HPM_CAL measurement at 2442MHz and are used to generate many additional
 * frequency points data without needing additional PLL calibrations. 
 *
 * @param hadm_chan_idx_list the pointer to an array of HADM channel index values that correspond to the cal_results array. Values may be in any order.
 * @param cal_results the pointer to an array of structures to store the interpolation results in raw format matching the frequency array.
 * @param num_freqs the number of frequencies at which interpolation should be performed.
 * @param hpm_cal_interp the HPM CAL value and effective cal frequency to be used for the basis of the interpolation.
 *
 * @return The status of the interpolation process.
 *
 * @pre XCVR_LCL_RsmInit() must be called successfully prior to using this routine.
 * @note The interpolation assumes data in the curve fit description structure is valid and performs no check on the input data other than NULLPTR check.
 * 
 */
xcvrLclStatus_t XCVR_LCL_InterpolatePllCal(const uint16_t * hadm_chan_idx_list, xcvr_lcl_pll_cal_data_t * cal_results, const uint16_t num_freqs, const xcvr_lcl_hpm_cal_interp_t * hpm_cal_interp);

/*!
 * @brief Function to trigger a manual DCOC calibration prior to RSM operations.
 *
 * This function triggers a RX warmup and a manual DCOC process in the receiver. The result of this process is that the DCOC registers are properly programmed for use in RSM operations.
 *
 * @param rate - the data rate.
 *
 * @return The status of the compensation process.
 *
 * 
 */
xcvrLclStatus_t XCVR_LCL_CalibrateDcoc(XCVR_RSM_SQTE_RATE_T rate);

/*!
 * @brief Function to configure TSM override signals to support keeping phase continuous in PLL.
 *
 * This function sets up the TSM overrides needed to keep the PLL TX and RX divider states consistent across multiple Channel Sounding events/subevents.
 *
 */
void XCVR_LCL_ContPhaseOvrd(void);

/*!
 * @brief Function to release TSM override signals used to keep phase continuous or measure non-continuous phase in PLL.
 *
 * This function releases all the TSM overrides configured in either of ::XCVR_LCL_ContPhaseOvrd() or ::XCVR_LCL_SetupPhaseMeasure()
 * or ::XCVR_LCL_EnablePhaseMeasure().
 *
 */
void XCVR_LCL_AllPhaseRelease(void);

/*!
 * @brief Function to override DCOC ADC and DAC to improve amplitude for measurement of  the current PLL phase angle.
 *
 * This function forces the DCOC 
 * ADC and DAC to offsets calculated from a previous DCOC calibration status result in order to improve the amplitude
 * of the resulting phase measurement.
 *
 * @note This routine requires a valid DCOC calibration prior be completed and the status results still available. This function
 * should be called only once before a calling XCVR_LCL_EnablePhaseMeasure(void). XCVR_LCL_AllPhaseRelease() must be 
 * called after all phase measurement is complete in order to remove the ADC and 
 * DAC overrides that are setup in XCVR_LCL_SetupPhaseMeasure().
 * 
 * @code
    #define RESID_TEST_NUM		(10U)
    typedef struct
    {
        int8_t i_resid;
        int8_t q_resid;
    } xcvr_dc_resid_t;
    xcvrLclStatus_t lclstatus;
    static xcvr_dc_resid_t dc_resid_continuous[RESID_TEST_NUM];
    static xcvr_dc_resid_t dc_resid_discontinuous[RESID_TEST_NUM];
    uint8_t count;
    uint32_t temp_resid;

    lclstatus = XCVR_LCL_CalibrateDcoc(XCVR_RSM_RATE_1MBPS);
    assert(lclstatus == gXcvrLclStatusSuccess);
    XCVR_LCL_SetupPhaseMeasure();
    XCVR_LCL_ContPhaseOvrd();
    for (count =0;count<RESID_TEST_NUM;count++)
    {
        XCVR_LCL_EnablePhaseMeasure(); 
        lclstatus = XCVR_LCL_CalibrateDcoc(XCVR_RSM_RATE_1MBPS);
        assert(lclstatus == gXcvrLclStatusSuccess);
        temp_resid = XCVR_RX_DIG->DCOC_DIG_CORR_RESULT;
        lclstatus = XCVR_LCL_ProcessPhaseMeasure(&dc_resid_continuous[count].i_resid, &dc_resid_continuous[count].q_resid, temp_resid);
        assert(lclstatus == gXcvrLclStatusSuccess);
    }
    XCVR_LCL_AllPhaseRelease();

    lclstatus = XCVR_LCL_CalibrateDcoc(XCVR_RSM_RATE_1MBPS);
    assert(lclstatus == gXcvrLclStatusSuccess);
    XCVR_LCL_SetupPhaseMeasure();
    for (count =0;count<RESID_TEST_NUM;count++)
    {
        XCVR_LCL_EnablePhaseMeasure();
        lclstatus = XCVR_LCL_CalibrateDcoc(XCVR_RSM_RATE_1MBPS);
        assert(lclstatus == gXcvrLclStatusSuccess);
        temp_resid = XCVR_RX_DIG->DCOC_DIG_CORR_RESULT;
        lclstatus = XCVR_LCL_ProcessPhaseMeasure(&dc_resid_discontinuous[count].i_resid, &dc_resid_discontinuous[count].q_resid, temp_resid);
        assert(lclstatus == gXcvrLclStatusSuccess);
    }
    XCVR_LCL_AllPhaseRelease();
    lclstatus = XCVR_LCL_CalibrateDcoc(XCVR_RSM_RATE_1MBPS);
    assert(lclstatus == gXcvrLclStatusSuccess);
   @endcode
 */
void XCVR_LCL_SetupPhaseMeasure(void);

/*!
 * @brief Function to configure TSM override signals to measure the current PLL phase angle.
 *
 * This function sets up the TSM overrides needed to prepare for measuring the current PLL phase. It must be called every time
 * before a phase measurement is performed (i.e. before the DCOC calibration)
 * 
 * @note 
 */
void XCVR_LCL_EnablePhaseMeasure(void);

/*!
 * @brief Function performs a measurement of the current PLL phase angle.
 *
 * This function uses the DC residual as a measurement of the PLL phase angle for comparison with a prior measurement.
 *
 * @param i_resid pointer to the location to store the DC residual measurement for the I channel
 * @param q_resid pointer to the location to store the DC residual measurement for the Q channel
 * @param dc_resid_val the 32 bit contents of the XCVR_RX_DIG->DCOC_DIG_CORR_RESULT register for processing. This is passed as a parameter
 * to ensure testability of the function.
 *
 * @return the status of the measurement process
 *
 * @note The I and Q residual values are intended to be used to calculate a phase angle as a measurement of the PLL phase. The absolute value
 * is not meaningful but comparison between two different measurements may be used to determine if the PLL has the same or inverted phase
 * (from one measurement to the next). 
 * After completion of this routine, a new DCOC calibration must be triggered in order to restore the state of the DCOC for subsequent operations.
 */
xcvrLclStatus_t XCVR_LCL_ProcessPhaseMeasure(int8_t * i_resid, int8_t * q_resid, uint32_t dc_resid_val);

/*!
 * @brief Function to apply a Carrier Frequency Offset compensation to the PLL for RSM operations.
 *
 * This function takes and input Carrier Frequency Offset compensation in Hz and calculates an offset to apply to the PLL numerator to implement the compensation
 *
 * @param cfo_in_hz the signed CFO to compensate in Hz. Positive CFO value == negative PLL frequency adjustment; Negative CFO value == positive PLL frequency adjustment; Zero == no adjustment.
 *
 * @return The status of the compensation process.
 *
 * 
 */
xcvrLclStatus_t XCVR_LCL_RsmCompCfo(int32_t cfo_in_hz);

/*!
 * @brief Function to read back a Carrier Frequency Offset compensation from the PLL for RSM operations.
 *
 * This function returns the Carrier Frequency Offset compensation in Hz based on the value in the PLL_OFFSET_CTRL register.
 *
 * @return The amount of compensation currently programmed, in Hz. 
 *
 * @note Due to the use of integer divide in this routine and in ::XCVR_LCL_RsmCompCfo(), the returned value may not be exactly the original requested compensation. 
 */
int32_t XCVR_LCL_RsmReadCfoComp(void); /* Read back current CFO compensation value (Hz) */


/*!
 * @brief Function to map from a HADM channel index to the channel number value to use for FSTEP programming.
 *
 * This function maps from a HADM channel index to the channel number value used to program the FSTEP channel number field according to HOP_TBL_CFG_OVRD format #3.
 *
 * @param hadm_chan_index The HADM standard specified channel index, ranging from 0 to 78 to select frequencies of 2402MHz up to 2480MHz.
 * @param fstep_chan_num the pointer to the location where the channel number value should be stored.
 *
 * @return The status of mapping process.
 * 
 */
xcvrLclStatus_t XCVR_LCL_MakeChanNumFromHadmIndex(uint8_t hadm_chan_index, uint16_t * fstep_chan_num);

/*!
 * @brief Function to return the dma buffer size and dma sequence length (us) of a configured rsm sequence.
 *
 * This function reads the rsm register configuration and iterate over the step settings to compute the total sequence buffer
 * size needed for dma iq capture and the dma sequence length in us ( to be used in antena switch configuration ).
 * The dma buffer size corresponds to the number of iq samples to be captured.
 *
 * @param[in]  fstep_settings frequency step list pointer (xcvr_lcl_fstep_t), the first element of a frequency step configuration array.
 * @param[in]  num_steps The number of step to be used
 * @param[in]  role (XCVR_RSM_RXTX_MODE_T) rsm mode : XCVR_RSM_TX_MODE or XCVR_RSM_RX_MODE
 * @param[out] dma_buffer_size (uint16_t) address to store the dma buffer size corresponding to the current configuration
 * @param[out] dma_seq_length_us (uint16_t) address to store the dma sequence length in us corresponding to the current configuration 
 * @param[in] ant_cnt (uint8_t) count of antenna active in this sequence.
 * @return The status of the function (xcvrLclStatus_t).
 * 
 */
xcvrLclStatus_t XCVR_LCL_GetRSMCaptureBufferSize(const xcvr_lcl_fstep_t * fstep_settings,
                                                 uint8_t num_steps,
                                                 XCVR_RSM_RXTX_MODE_T role,
                                                 uint16_t * dma_buffer_size,
                                                 uint16_t * dma_seq_length_us,
                                                 uint8_t ant_cnt);

/*!
 * @brief Function to count the number of FCS, Pk-Pk , and Pk-Tn-Tn-Pk steps within an overall frequency step list.
 *
 * This function counts the number of FCS, Pk-Pk , and Pk-Tn-Tn-Pk steps within an overall frequency step list in 
 * order to verify that PN RAM and RTT RAM will not be overrun. This is due to the difference in the Fstep RAM
 * length and the length of the PN and RTT RAMs.
 *
 * @param fstep_settings the pointer to a structure for frequency step programming, assumed to be an array.
 * @param num_steps the number of frequency steps in the input list.
 *
 * @return The count of FCS, Pk-Pk , and Pk-Tn-Tn-Pk steps within the overall frequency step list. A value of 0xFFU is returned in error cases.
 * 
 */
uint8_t XCVR_LCL_CountPnRttSteps(const xcvr_lcl_fstep_t * fstep_settings, uint16_t num_steps);

#endif /* #if defined(RADIO_IS_GEN_4P5) */

/*! @}*/

#if defined(__cplusplus)
}
#endif

#endif /* NXP_XCVR_LCL_CTRL_H */



