/*
 * Copyright 2015 Freescale
 * Copyright 2016,2019-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.
 */

#ifndef __USB_AUDIO_H__
#define __USB_AUDIO_H__ 1

//#include "app_defines.h"
#include "usb.h"
#include "usb_device_class.h"
#include "usb_device_config.h"

/*******************************************************************************
* Definitions
******************************************************************************/


/* TODO: Move this to usb_descriptor.h */
/** Amount of milliseconds/microseconds used to re-calculate feedback */
#define USB_AUDIO_FEEDBACK_REFRESH_RATE               (1)   /* Refresh Rate 2**n ms */

#define AUDIO_APP_FEEDBACK_UPDATE_MS  ((1 << USB_AUDIO_FEEDBACK_REFRESH_RATE))
#define AUDIO_APP_FEEDBACK_UPDATE_US  (AUDIO_APP_FEEDBACK_UPDATE_MS * 1000u)

#define AUDIO_SAMPLING_RATE_KHZ (48)
#define AUDIO_SAMPLING_RATE_16KHZ (16)
#define AUDIO_SAMPLING_RATE (AUDIO_SAMPLING_RATE_KHZ * 1000)

#define AUDIO_RECORDER_DATA_WHOLE_BUFFER_LENGTH (16 * 2)
#define AUDIO_SPEAKER_DATA_WHOLE_BUFFER_LENGTH (16 * 2)
#define AUDIO_BUFFER_UPPER_LIMIT(x) (((x)*5) / 8)
#define AUDIO_BUFFER_LOWER_LIMIT(x) (((x)*3) / 8)
#define TSAMFREQ2BYTES(f) (f & 0xFFU), ((f >> 8U) & 0xFFU), ((f >> 16U) & 0xFFU)
#define TSAMFREQ2BYTESHS(f) (f & 0xFFU), ((f >> 8U) & 0xFFU), ((f >> 16U) & 0xFFU), ((f >> 24U) & 0xFFU)
#define AUDIO_ADJUST_MIN_STEP (0x10)

typedef struct _usb_audio_settings {
    uint8_t curMute;
    uint8_t curVolume[2];
    uint8_t minVolume[2];
    uint8_t maxVolume[2];
    uint8_t resVolume[2];
    uint8_t curBass;
    uint8_t minBass;
    uint8_t maxBass;
    uint8_t resBass;
    uint8_t curMid;
    uint8_t minMid;
    uint8_t maxMid;
    uint8_t resMid;
    uint8_t curTreble;
    uint8_t minTreble;
    uint8_t maxTreble;
    uint8_t resTreble;
    uint8_t curAutomaticGain;
    uint8_t curDelay[2];
    uint8_t minDelay[2];
    uint8_t maxDelay[2];
    uint8_t resDelay[2];
    uint8_t curLoudness;
    uint8_t curSamplingFrequency[3];
    uint8_t minSamplingFrequency[3];
    uint8_t maxSamplingFrequency[3];
    uint8_t resSamplingFrequency[3];
} usb_audio_settings_t;

typedef struct _usb_audio_composite_struct
{
    usb_device_handle deviceHandle;
#if USB_CHAT_SPEAKER_ENABLE
    class_handle_t audioChatSpeakerHandle;
    usb_audio_settings_t chatSpeakerSettings;
#endif
#if USB_GAME_SPEAKER_ENABLE
    class_handle_t audioGameSpeakerHandle;
    usb_audio_settings_t gameSpeakerSettings;
#endif
#if USB_RECORDER_ENABLE
    class_handle_t audioRecorderHandle;
    usb_audio_settings_t recSettings;
#endif
    uint8_t copyProtect;
    uint8_t currentConfiguration;
    uint8_t speed;
    uint8_t attach;           /**< Store whether or not the audio device is attached */
    bool enableStreaming;     /**< Audio samples will only be sent/received when the audio device is enabled */
    volatile uint32_t codecTask;
} usb_audio_composite_struct_t;

/**
 * @brief USB Audio Speaker instances
 */
typedef enum _usb_speaker_instance {
#if USB_CHAT_SPEAKER_ENABLE
    kUSB_SPEAKER_INSTANCE_Chat,  /**< Speaker instance for chat/voice */
#endif
#if USB_GAME_SPEAKER_ENABLE
    kUSB_SPEAKER_INSTANCE_Game,  /**< Speaker instance for game */
#endif
    kUSB_SPEAKER_INSTANCE_Count, /**< Used as counter for number of USB Audio Speaker instances */
} usb_speaker_instance_t;

#if USB_CTRL_SERVICE_TX_ENABLE
/**
 * Stop TX I2S transfers
 * This has the prototype of a DPC function to enable ordering a
 * disable from ISR
 *
 * @param cookie Not used, due to the DPC prototype
 */
void USB_AudioUnifiedStopTx(void *cookie);
#endif

/**
 * Stop RX I2S transfers
 * This has the prototype of a DPC function to enable ordering a
 * disable from ISR
 *
 * @param cookie Not used, due to the DPC prototype
 */
void USB_AudioUnifiedStopRx(void *cookie);

/**
 * @brief Enable/disable audio streaming; it's enabled by default.
 *
 * The audio device should be enabled in order for it to process audio samples (both TX and RX).
 * By disabling the audio device, the samples will simply be ignored.
 */
void USB_AudioEnableStreaming(bool enable);

/**
 * @brief device Audio callback function.
 *
 * This function handle the Audio class specified event.
 * Called when:
 * - USB audio packet is sent (forward channel)
 * - USB audio packet recieved (backchannel)
 * - USB audio request is received (volume change, ...)
 * - Feedback request is received
 * .
 * @param handle          The USB class handle.
 * @param event           The USB device event type.
 * @param param           The parameter of the class specific event.
 * @return kStatus_USB_Success or error.
 */
usb_status_t USB_DeviceAudioCompositeCallback(class_handle_t handle, uint32_t event, void *param);

#endif /* __USB_AUDIO_GENERATOR_H__ */
