/**
* @file         spv40xx_hal_dma.h
* @brief        XXX
* @details      XXX
* @author       涂龙
* @date         2023-05-10 14:16
* @version      V0.0
* @copyright    Copyright (c) 2017-2023  SpaceTouch Inc.
*/
#ifndef _HAL_DMA_H_
#define _HAL_DMA_H_

#include "hal_def.h"
#include "base_space.h"




typedef struct
{
    uint32_t channel;           /*!<指定使用dma通道。
                                     参数范围0-7 */

    uint32_t src_inc;           /*!<指定源基地址是否自增。
                                    参数值选至 dma_addr_type_t*/
    uint32_t dst_inc;           /*!<指定目的地址是否自增
                                    参数值选至 dma_addr_type_t*/

    uint32_t src_data_width;    /*!<指定源数据的宽度。
                                    参数值可以是 dma_data_width_t*/
    uint32_t dst_data_width;    /*!<指定目的数据的宽度。
                                    参数值选至 dma_data_width_t*/

    uint32_t src_data_loc;      /*!<指定源数据存放在32bit中高24bit部分或低24bit部分，只有src_data_size为24bit有效。
                                    参数值选至 dma_data_location_select_t*/
    uint32_t dst_data_loc;      /*!<指定目的数据存放在32bit中高24bit部分或低24bit部分，只有dst_data_size为24bit有效。
                                    参数值选至 dma_data_location_select_t*/

    uint32_t memory_burst;      /*!<指定源和目的传输的burst大小。
                                    只有源和目的地址为内存时有效
                                    参数值选至 dma_burst_length_t*/

    uint32_t mode;              /*!<指定传输模式。
                                    参数值选至 dma_mode_t*/
    uint32_t priority;          /*!<指定对应dma通道优先级。
                                    范围0-7，值越大优先级越高*/

} DMA_InitTypeDef;



typedef enum
{
    HAL_DMA_STATE_RESET             = 0x00U,  /*!< DMA not yet initialized or disabled */
    HAL_DMA_STATE_READY             = 0x01U,  /*!< DMA initialized and ready for use   */
    HAL_DMA_STATE_BUSY              = 0x02U,  /*!< DMA process is ongoing              */
    HAL_DMA_STATE_ERROR             = 0x03U,  /*!< DMA error state                     */
    HAL_DMA_STATE_PAUSE             = 0X04U,  /*!< DMA Pause state                   */
} HAL_DMA_StateTypeDef;

typedef enum
{
    HAL_DMA_XFER_CPLT_CB_ID         = 0x00U,  /*!< Full transfer     */
    HAL_DMA_XFER_HALFCPLT_CB_ID     = 0x01U,  /*!< Half Transfer     */
    HAL_DMA_XFER_ALL_CB_ID          = 0x02U   /*!< All               */
} HAL_DMA_CallbackIDTypeDef;

typedef struct __DMA_HandleTypeDef
{
    DMA_InitTypeDef init;                                        /*!< DMA communication parameters           */

    volatile HAL_DMA_StateTypeDef   state;                                   /*!< DMA transfer state                     */

    void (* xfer_cplt_callback)(struct __DMA_HandleTypeDef *hdma, void *param);            /*!< DMA transfer complete callback         */

    void (* xfer_half_cplt_callback)(struct __DMA_HandleTypeDef *hdma, void *param);    /*!< DMA Half transfer complete callback
                                                                                 ！！！当搬运数据为奇数搬运单位，没有半搬运完成中断。*/

    uint32_t xfer_half_cplt_flag;                               /*!< the flag of DMA Half transfer complete callback                      */
} DMA_HandleTypeDef;

typedef enum
{
    CH0 = 0x00U,  /*!< DMA channel 0 */
    CH1,
    CH2,
    CH3,
    CH4,
    CH5,
    CH6,
    CH7,
    DMA_CHANNLE_DEFAULT,
} HAL_DMA_Ch_TypeDef;

typedef enum
{
    CH_FREE,
    CH_BUSY,
} hal_dma_ch_status_typedef;


typedef struct _HAL_DMA_Handle_CH_TypeDef
{
    DMA_HandleTypeDef  *handle;
    HAL_DMA_Ch_TypeDef ch;
    hal_dma_ch_status_typedef     ch_status;/*是否为空闲状态*/
    void *param;
} HAL_DMA_Handle_CH_TypeDef;

#define TOTAL_DMA_CH_NUM    8
extern HAL_DMA_Handle_CH_TypeDef   dma_ch_status[TOTAL_DMA_CH_NUM];

HAL_StatusTypeDef hal_dma_init(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef hal_dma_deinit(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef  hal_dma_ch_alloc(DMA_HandleTypeDef *hdma, void *param);
HAL_StatusTypeDef  hal_dma_ch_free(DMA_HandleTypeDef *hdma, void *param);
HAL_StatusTypeDef hal_dma_start(DMA_HandleTypeDef *hdma, uint32_t srca_ddress, uint32_t dst_address, uint32_t data_length, void *param);
HAL_StatusTypeDef hal_dma_start_it(DMA_HandleTypeDef *hdma, uint32_t src_address, uint32_t dst_address, uint32_t data_length, void *param);
HAL_StatusTypeDef hal_dma_abort(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef hal_dma_pause(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef hal_dma_resume(DMA_HandleTypeDef *hdma);
void hal_dma_irqhandler(DMA_HandleTypeDef *hdma, void *param);
void hal_dma_handle(void);
HAL_StatusTypeDef hal_dma_register_callback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(struct __DMA_HandleTypeDef *hdma, void *param));
HAL_StatusTypeDef hal_dma_unregister_callback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID);
HAL_DMA_StateTypeDef hal_dma_get_state(DMA_HandleTypeDef *hdma);
HAL_StatusTypeDef hal_dma_set_default(DMA_HandleTypeDef *hdma, void *param);
uint32_t hal_dma_get_pd(uint32_t chx);
void hal_dma_clear_pd(uint32_t chx);

#define __HAL_DMA_ENABLE(__HANDLE__)      (DEV_DMAC->DMA_EN = (1UL<<(__HANDLE__->init.channel))|(1UL<<(__HANDLE__->init.channel+16)))
#define __HAL_DMA_DISABLE(__HANDLE__)     (DEV_DMAC->DMA_EN = (1UL<<(__HANDLE__->init.channel+16)))

#define __HAL_DMA_PAUSE(__HANDLE__)      (DEV_DMAC->DMA_CHN[__HANDLE__->init.channel].CFG_f.PAUSE = 1)
#define __HAL_DMA_RESUME(__HANDLE__)     (DEV_DMAC->DMA_CHN[__HANDLE__->init.channel].CFG_f.PAUSE = 0)

#define __HAL_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (DEV_DMAC->DMA_IE&(__INTERRUPT__<<(__HANDLE__->init.channel)))


#define IS_DMA_CHANNEL(CHANNEL)         (((CHANNEL)==0UL) \
                                        ||((CHANNEL)==1UL) \
                                        ||((CHANNEL)==2UL) \
                                        ||((CHANNEL)==3UL) \
                                        ||((CHANNEL)==4UL) \
                                        ||((CHANNEL)==5UL) \
                                        ||((CHANNEL)==6UL) \
                                        ||((CHANNEL)==7UL) \
                                        )

#define IS_DMA_INC_STATE(STATE)         (((STATE)==DMA_Address_Type_Fix)|| \
                                         ((STATE)==DMA_Address_Type_Inc))

#define IS_DMA_DATA_WIDTH(WIDTH)        (((WIDTH)==DMA_Data_Width_8Bit)|| \
                                         ((WIDTH)==DMA_Data_Width_16Bit)|| \
                                         ((WIDTH)==DMA_Data_Width_24Bit)|| \
                                         ((WIDTH)==DMA_Data_Width_32Bit))

#define IS_DMA_DATA_LOCATION(LOC)       (((LOC)==DMA_Data_Location_Select_Low)|| \
                                         ((LOC)==DMA_Data_Location_Select_High))

#define IS_DMA_MEMORY_BURST(BUTSR)      (((BUTSR)==DMA_Burst_Length_Burst1)|| \
                                         ((BUTSR)==DMA_Burst_Length_Burst2)|| \
                                         ((BUTSR)==DMA_Burst_Length_Burst4)|| \
                                         ((BUTSR)==DMA_Burst_Length_Burst8))


#define IS_DMA_MODE(MODE)               (((MODE)==ENABLE)|| \
                                         ((MODE)==DISABLE))


#define IS_DMA_PRIORITY(PRIORITY)       (((PRIORITY)==0UL) \
                                        ||((PRIORITY)==1UL) \
                                        ||((PRIORITY)==2UL) \
                                        ||((PRIORITY)==3UL) \
                                        ||((PRIORITY)==4UL) \
                                        ||((PRIORITY)==5UL) \
                                        ||((PRIORITY)==6UL) \
                                        ||((PRIORITY)==7UL) \
                                        )

#define IS_DMA_BUFFER_SIZE(SIZE)        (((SIZE)>=1UL)&&((SIZE)<=65536UL))

#endif /* SPV_HAL_DMA_H_ */
