/*
 * Copyright 2017-2020 NXP
 * This software is owned or controlled by NXP and may only be used strictly
 * in accordance with the applicable license terms.  By expressly accepting
 * such terms or by downloading, installing, activating and/or otherwise using
 * the software, you are agreeing that you have read, and that you agree to
 * comply with and are bound by, such license terms.  If you do not agree to
 * be bound by the applicable license terms, then you may not retain, install,
 * activate or otherwise use the software.
 */

/**
 * @defgroup KL_MODULES_AUDIOSERVICE_API API
 * @ingroup KL_MODULES_AUDIOSERVICE
 * @anchor audio_service
 *
 * The audio service is responsible for @ref KL_MODULES_AUDIOSERVICE_TX_API "sending (TX)"
 * and @ref KL_MODULES_AUDIOSERVICE_RX_API "receiving (RX)" audio data over I2S.
 *
 * @anchor AUDIO_SERVICE_TX_ENABLE
 * The **TX functionality** enables the sending of audio data to the I2S, and will be enabled
 * automatically if the number of speakers (AUDIO_SPEAKER_CNT) is greater than zero.
 *
 * The user has to configure the number of speakers (AUDIO_SPEAKER_CNT) in order for the service to
 * compile successfully. Currently, it is set to the number of speakers implemented on USB level.
 *
 * @anchor AUDIO_SERVICE_RX_ENABLE
 * The **RX functionality** enables the receiving of audio data from the I2S. The user has to
 * explicitly enable or disable this functionality by defining the value for AUDIO_SERVICE_RX_ENABLE
 * as 1 or 0. Currently, the value being configured depends on whether or not the audio recorder is
 * enabled on application level (USB_RECORDER_ENABLE in "app_defines.h").
 *
 * @attention If used together with the @ref NxH "NxH service" and/or @ref HCI "HCI layer",
 * make sure to read @ref nxh_audio_limitation "service limitations"
 *
 * @{
 */

#ifndef AUDIO_H_
#define AUDIO_H_

/* ---------------------------------------------------------------------------- */
/* Include files                                                                */
/* ---------------------------------------------------------------------------- */

#include <stdint.h>
#include "fsl_sai.h"
#include "error.h"

/* ---------------------------------------------------------------------------- */
/* Configuration                                                                */
/* ---------------------------------------------------------------------------- */

/**
 * Set the number of speakers implemented by the audio service (AUDIO_SPEAKER_CNT)
 * equal to the number of speakers implemented on USB level or application(voice prompt).
 */
#ifdef AUDIO_SERVICE_SPEAKER_CNT
    #define AUDIO_SPEAKER_CNT  AUDIO_SERVICE_SPEAKER_CNT
#endif

/**
 * Enable the RX functionality (AUDIO_SERVICE_RX_ENABLE) if and only if the application
 * uses the audio recorder.
 */
#ifdef AUDIO_SERVICE_RECORDER_CNT
    #define AUDIO_SERVICE_RX_ENABLE  AUDIO_SERVICE_RECORDER_CNT
#endif

/* ---------------------------------------------------------------------------- */
/* Defines                                                                      */
/* ---------------------------------------------------------------------------- */
#define AUDIO_SERVICE_DMA_CHANNEL_OUT       (0)
#define AUDIO_SERVICE_DMA_CHANNEL_IN        (2)
#define AUDIO_SERVICE_DMA_CHANNEL_LINK_OUT  (1)
#define AUDIO_SERVICE_DMA_CHANNEL_LINK_IN   (3)

#define AUDIO_SERVICE_DMA_BASE              (DMA0)
#define AUDIO_SERVICE_DMAMUX_BASE           (DMAMUX0)


/**
 * The audio service requires:
 * - the number of speakers (AUDIO_SPEAKER_CNT) to be defined
 * - the RX functionality (AUDIO_SERVICE_RX_ENABLE) to be explicitly enabled/disabled
 */

/**
 * Automatically enable the TX functionality (AUDIO_SERVICE_TX_ENABLE) if required.
 */

#define AUDIO_SERVICE_TX_ENABLE  1
#define AUDIO_SERVICE_RX_ENABLE  1

#define USB_CTRL_SERVICE_TX_ENABLE  1
#define USB_CTRL_SERVICE_RX_ENABLE  1


/**
 * Set the nr of TX audio channels
 */
#define TX_AUDIO_CHANNELS  (2)
/**
 * Set the nr of RX audio channels
 */
#define RX_AUDIO_CHANNELS  (1)

/**
 * Set the audio rx sample size
 * 2*8 = 16bits
 */
#define AUDIO_RX_SAMPLE_SIZE_BYTES  (2)

/**
 * Audio I2s Frame size
 */
#define AUDIO_I2S_FRAME_SIZE  (2)

/**
 * audio interface word length 2 bytes
 */
#define AUDIO_IF_WORD_LENGTH_2_BYTES  (2)

/**
 * audio interface word length 3 bytes
 */
#define AUDIO_IF_WORD_LENGTH_3_BYTES  (3)

/**
 * audio interface word length 4 bytes
 */
#define AUDIO_IF_WORD_LENGTH_4_BYTES  (4)

/**
 * audio interface word length 8 bits
 */
#define AUDIO_IF_WORD_LENGTH_8_BITS  (8)

/**
 * audio interface word length 16 bits
 */
#define AUDIO_IF_WORD_LENGTH_16_BITS  (AUDIO_IF_WORD_LENGTH_8_BITS * AUDIO_IF_WORD_LENGTH_2_BYTES)

#define AUDIO_IF_WORD_LENGTH_25_BITS  (25)

/**
 * audio interface word length 32 bits
 */
#define AUDIO_IF_WORD_LENGTH_32_BITS  (AUDIO_IF_WORD_LENGTH_8_BITS * AUDIO_IF_WORD_LENGTH_4_BYTES)

/**
 *  Set the sampling rate to 48kHz
 */
#define AUDIO_SERVICE_SAMPLING_RATE_48  (48)

/**
 * Set the sampling rate
 */
#ifndef USE_SAMPLERATE_32KHZ
/* Setting 48kHz sample rate on I2S_FS with result in (2 * 32bits/word * 48000 Hz = 3.07 MHz I2S_BCLK */
    #define AUDIO_SERVICE_SYSTEM_SAMPLING_RATE  (AUDIO_SERVICE_SAMPLING_RATE_48)
#endif



/**
 * Audio transmission complete callback prototype.
 * This will be called by the module when the DMA transfer of AudioTX is completed.
 *
 * @param audioTxTransferSize size of the data transfered via DMA.
 * @param status returns kERROR_Ok if audio tx write was success, kERROR_Fail if otherwise.
 */
typedef void (*audio_tx_write_complete_cb_t)(uint16_t audioTxTransferSize, error_t status);

/**
 * @brief Required to control the current status of the Audio Service
 */
typedef enum _audioStatus {
    AUDIO_SERVICE_TX_COMPLETE,
    AUDIO_SERVICE_RX_COMPLETE,
    AUDIO_SERVICE_TX_STARTED,
    AUDIO_SERVICE_RX_STARTED
}audioStatus_t;

/**
 * @brief Required to configure the current status variable that control the Audio Service.
 */
typedef enum _audioStatusMasks {
    AUDIO_SERVICE_TX_COMPLETE_MASK = (1 << AUDIO_SERVICE_TX_COMPLETE),
    AUDIO_SERVICE_RX_COMPLETE_MASK = (1 << AUDIO_SERVICE_RX_COMPLETE),
    AUDIO_SERVICE_TX_STARTED_MASK  = (1 << AUDIO_SERVICE_TX_STARTED),
    AUDIO_SERVICE_RX_STARTED_MASK  = (1 << AUDIO_SERVICE_RX_STARTED)
}audioStatusMasks_t;

/**
 * @brief Required to Set the audio interface word length
 */
typedef enum _audioIfWordLength {
    AUDIO_SERVICE_AUDIO_IF_WORD_LENGTH_16_BITS = 0,
    AUDIO_SERVICE_AUDIO_IF_WORD_LENGTH_32_BITS = 1,
    AUDIO_SERVICE_AUDIO_IF_WORD_LENGTH_Count
}audioIfWordLength_t;

/**
 * @brief Required to Set the audio format.
 * Audio service only support I2S_Master, I2S_Slave and TDM_Typical.
 */
typedef enum _audioCtrlFormat {
    AUDIO_SERVICE_FORMAT_I2S_MASTER  = 0,
    AUDIO_SERVICE_FORMAT_I2S_SLAVE   = 1,
    AUDIO_SERVICE_FORMAT_TDM_TYPICAL = 2,
    AUDIO_SERVICE_FORMAT_Count
}audioCtrlFormat_t;

/**
 * Audio service init config struct
 */
typedef struct _audio_ctrl_config {
    bool enableLatencyDebug;                             /**< flag to enable/disable latency debug */
    audioIfWordLength_t audioIfWordLength;               /**< audio interface word length */
    audioCtrlFormat_t audioFormat;                       /**< audio format */
    bool serviceControlsI2sPins;                         /**< defines if audio service controls I2S pins or not */
    audio_tx_write_complete_cb_t audioTxWriteCompleteCb; /**< audio tx complete callback */
} audio_ctrl_config_t;

#endif /* AUDIO_H_ */

/** @} */
