/*
 * Copyright 2021 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _SRTM_PDM_SDMA_ADAPTER_H_
#define _SRTM_PDM_SDMA_ADAPTER_H_

#include "srtm_audio_service.h"
#include "fsl_pdm_sdma.h"

/*!
 * @addtogroup srtm_service
 * @{
 */

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#ifndef SRTM_PDM_SDMA_ADAPTER_USE_HWVAD
#define SRTM_PDM_SDMA_ADAPTER_USE_HWVAD (1U)
#endif

#define SRTM_PDM_SDMA_MAX_LOCAL_PERIOD_ALIGNMENT (4U)

/*! @brief Extra device intitialize function for PDM SDMA adapter. */
typedef void (*pdm_dev_init)(bool enable);
/*! @brief Extra device configuration function based on format and sample rate, return PMD clock source in HZ. */
typedef uint32_t (*pdm_dev_conf)(srtm_audio_format_type_t format, uint32_t srate);

/*! @brief Misc configuration structure. */
typedef struct _pdm_misc_set
{
    pdm_dev_init audioDevInit; /*!< Audio device init function. */
    pdm_dev_conf audioDevConf; /*!< config audio device based on format and sample rate, return source clock in HZ */
} pdm_misc_set_t;

/*! @brief PDM SDMA configuration.  */
typedef struct _srtm_pdm_sdma_config
{
    pdm_config_t config;                /*!< PDM user configuration. */
    pdm_channel_config_t channelConfig; /*!< PDM channel configurations. */
    uint32_t pdmSrcClk;                 /*!< PDM source clock in Hz. */
    uint32_t dmaChannel;                /*!< DMA channel. */
    uint8_t channelPriority;            /*!< The priority of DMA channel. */
    bool stopOnSuspend;                 /*!< Stop capture when received suspend command. */
    uint32_t eventSource;               /*!< DMA request source. */

    sdma_context_data_t rxContext;
    pdm_misc_set_t extendConfig;
} srtm_pdm_sdma_config_t;

/*! @brief PDM SDMA local buffer.  */
typedef struct _srtm_pdm_sdma_local_buf
{
    uint8_t *buf;              /*!< Pointer of the buffer */
    uint32_t bufSize;          /*!< bytes of the whole local buffer */
    uint32_t periods;          /*!< periods in local buffer */
    uint32_t samplesPerPeriod; /*!< number of samples per period (ignored if set to 0 - otherwise "periods" field is
re-computed based on the value and bufSize) */
} srtm_pdm_sdma_local_buf_t;

#if SRTM_PDM_SDMA_ADAPTER_USE_HWVAD
typedef enum _srtm_pdm_hwvad_mode
{
    kSRTM_PDM_Hwvad_Disabled          = 0U,
    kSRTM_PDM_Hwvad_EnergyBasedMode   = 1U,
    kSRTM_PDM_Hwvad_EnvelopeBasedMode = 2U,
} srtm_pdm_hwvad_mode_t;

typedef struct _srtm_pdm_hwvad_config
{
    srtm_pdm_hwvad_mode_t mode;
    pdm_hwvad_config_t hwvadConfig;
    pdm_hwvad_noise_filter_t noiseFilterConfig;
    pdm_hwvad_zero_cross_detector_t zcdConfig;
    uint32_t signalGain;
} srtm_pdm_hwvad_config_t;

/*! @brief HWVAD callback function pointer. The callback is called when voice activity is detected by HWVAD.
 */
typedef void (*srtm_pdm_sdma_hwvad_callback_t)(srtm_sai_adapter_t adapter, void *params);
#endif /* SRTM_PDM_SDMA_ADAPTER_USE_HWVAD */

/*! @brief The callback function pointer.  Voice data can be passed to application via callback when the host side is
 * suspend. The callback is also a notification to the application for the host side resumes from suspend when the data
 * and bytes are 0(NULL). */
typedef void (*srtm_pdm_sdma_data_callback_t)(srtm_sai_adapter_t adapter, void *data, uint32_t bytes, void *params);

/*******************************************************************************
 * API
 ******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif

/*!
 * @brief Create PDM SDMA adapter.
 *
 * @param pdm PDM base address.
 * @param dma DMA base address.
 * @param rxConfig PDM Rx channel configuration.
 * @return SRTM PDM SDMA adapter on success or NULL on failure.
 */
srtm_sai_adapter_t SRTM_PdmSdmaAdapter_Create(PDM_Type *pdm, SDMAARM_Type *dma, srtm_pdm_sdma_config_t *rxConfig);

/*!
 * @brief Destroy PDM SDMA adapter.
 *
 * @param adapter PDM SDMA adapter to destroy.
 */
void SRTM_PdmSdmaAdapter_Destroy(srtm_sai_adapter_t adapter);

/*!
 * @brief Get the audio service status.
 * @param adapter PDM SDMA adapter.
 * @param pRxState status pointer.
 */
void SRTM_PdmSdmaAdapter_GetAudioServiceState(srtm_sai_adapter_t adapter, srtm_audio_state_t *pRxState);

/*!
 * @brief Set local buffer to use in DMA transfer. If local buffer is set, the audio data will be captured
 * and transfered to local buffer, then copied to share buffer. Otherwise the data will be
 * transfered from PDM interface to shared buffer directly.
 * NOTE: it must be called before service start.
 *
 * @param adapter PDM SDMA adapter to set.
 * @param localBuf Local buffer information to be set to the adapter RX path.
 */
void SRTM_PdmSdmaAdapter_SetRxLocalBuf(srtm_sai_adapter_t adapter, srtm_pdm_sdma_local_buf_t *localBuf);

/*!
 * @brief When the host driver suspends, voice data can be passed to application via callback.
 *        When the host driver is waking up, the notfication is sent via callback.
 *        The callback is called in SRTM dispatcher task context and should not cost much time.
 *
 * @param adapter PDM SDMA adapter instance.
 * @param cb Callback function pointer.
 * @param param Callback function argument to be passed back to applicaiton.
 */
void SRTM_PdmSdmaAdapter_SetDataHandlerOnHostSuspend(srtm_sai_adapter_t adapter,
                                                     srtm_pdm_sdma_data_callback_t cb,
                                                     void *param);

/*!
 * @brief When key word detected, voice data will be sent to host again.
 *
 * @param adapter PDM SDMA adapter instance.
 */
void SRTM_PdmSdmaAdapter_ResumeHost(srtm_sai_adapter_t adapter);

#if SRTM_PDM_SDMA_ADAPTER_USE_HWVAD

/* clang-format off */
/*!
 * @brief Setup HWVAD. This function is used to configure the HWVAD function of PDM module, the API should be called
 * before the start of PDM capture. Once successfully configured and HWVAD mode is not kSRTM_PDM_Hwvad_Disabled mode,
 * the HWVAD will be enabled when the PDM capture starts. SRTM_PdmSdmaAdapter_EnableHwvad can be used to disable or
 * re-enable the HWVAD function during capture.
 * Sample configurations for EnvelopeBasedMode,
 * code
 * static srtm_pdm_hwvad_config_t pdm_hwvad_config = {
 *     .mode = kSRTM_PDM_Hwvad_EnvelopeBasedMode,
 *     .hwvadConfig.channel = 0U,
 *     .hwvadConfig.initializeTime = 10U,
 *     .hwvadConfig.cicOverSampleRate = 0U,
 *     .hwvadConfig.inputGain = 0U,
 *     .hwvadConfig.frameTime = 10U,
 *     .hwvadConfig.cutOffFreq        = kPDM_HwvadHpfBypassed,
 *     .hwvadConfig.enableFrameEnergy = false,
 *     .hwvadConfig.enablePreFilter   = true,
 *     .noiseFilterConfig.enableAutoNoiseFilter = false,
 *     .noiseFilterConfig.enableNoiseMin        = true,
 *     .noiseFilterConfig.enableNoiseDecimation = true,
 *     .noiseFilterConfig.noiseFilterAdjustment = 0U,
 *     .noiseFilterConfig.noiseGain             = 7U,
 *     .noiseFilterConfig.enableNoiseDetectOR   = true,
 *     .signalGain = 0U,
 *  };
 * code
 * @param adapter PDM SDMA adapter instance.
 * @param hwvadConfig The HWVAD configuration structure.
 * @param cb The callback function pointer.
 * @param param Callback function argument to be passed back to applicaiton.
 * @return Configured the HWVAD successfully or with failure.
 */
/* clang-format on */
srtm_status_t SRTM_PdmSdmaAdapter_ConfigHwvad(srtm_sai_adapter_t adapter,
                                              const srtm_pdm_hwvad_config_t *hwvadConfig,
                                              srtm_pdm_sdma_hwvad_callback_t cb,
                                              void *param);

/*!
 * @brief Enable/Disable the HWVAD, this API is used to enable/disable the HWVAD during PDM capture.
 *
 * @param adapter PDM SDMA adapter instance.
 * @param enable Enable or disable the HWVAD.
 */
void SRTM_PdmSdmaAdapter_EnableHwvad(srtm_sai_adapter_t adapter, bool enable);
#endif /* SRTM_PDM_SDMA_ADAPTER_USE_HWVAD */
/*******************************************************************************
 * Definitions from other files
 ******************************************************************************/

#ifdef __cplusplus
}
#endif

/*! @} */

#endif /* __SRTM_SAI_SDMA_ADAPTER_H__ */
