/**
  ******************************************************************************
  * @file    dma_drv.h
  * @author  Product application department
  * @version V1.0
  * @date    2020.02.13
  * @brief   Header file of DMA DRV module.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_DRV_H
#define __DMA_DRV_H

#ifdef __cplusplus
extern "C"
{
#endif

/* Includes ------------------------------------------------------------------*/
#include "drv_reg.h"


extern DMAC_TypeDef *m_dma_control;//global struct variable for for DMAC registers
extern DMAC_ChannelTypeDef *m_dma_channel[]; 

#ifdef FILE_OUT
/**@defgroup DRV 3 HAL driver
  *
  *@{
  */
  
/** @defgroup DRV_DMA DMA
  *
  *@{
  */
#endif
/*** 宏定义 *******************************************************************/
#ifdef FILE_OUT
/** @defgroup DRV_DMA_Exported_Macros Exported Macros
  *
  * @{
  */
#endif

#define DMAC_HWNUM				(1)
#define DMAC_CHNUM				(4)

#define DMACCH0					(0)
#define DMACCH1					(1)
#define DMACCH2					(2)
#define DMACCH3					(3)

#define DMA_IE    (0x01)

#define SIEC        0x0<<9
#define SDEC        0x1<<9
#define SNOCHG      0x2<<9
#define DNOCHG      0x2<<7

#define DI        (0x0)//increment
#define SI        (0x0)

#define DWIDTH_B    0x0<<1
#define DWIDTH_HW   0x1<<1
#define DWIDTH_W    0x2<<1
#define DWIDTH_DW   0x3<<1
#define SWIDTH_B    0x0<<4
#define SWIDTH_HW   0x1<<4
#define SWIDTH_W    0x2<<4
#define SWIDTH_DW   0x2<<4

#define LLP_SRC_EN 0x1<<28
#define LLP_DST_EN 0x1<<27

#define M2M_DMA  0x0<<20
#define M2P_DMA  0x1<<20
#define P2M_DMA  0x2<<20
#define P2P_DMA  0x3<<20
#define P2M_PER  0x4<<20
#define P2P_SRC  0x5<<20
#define M2P_PER  0x6<<20
#define P2P_DST  0x7<<20

#define DBSIZE_8 0x2<<11
#define SBSIZE_8 0x2<<14

#define DST_PER_DAC				(0x08<<11)

#define CHANNEL_UMASK(n)         (((1<<n)<<8) | (1<<n))
#define CHANNEL_WRITE_ENABLE(n)  ((1<<n)<<8)
#define CHANNEL_ENABLE(n)        (1<<n)
#define CHANNEL_STAT(n)          (1<<n)

#define DRV_DMAC_CH_MAX                                       (4)
#define _dmac_ch_en(pdmac,ch)                                 _reg_write(pdmac->CHEN, (((1<<ch)<<DMAC_CH_WE_EN_SHIFT_MASK) | (1<<ch)))
#define _dmac_ch_dis(pdmac,ch)                                _reg_write(pdmac->CHEN, (((1<<ch)<<DMAC_CH_WE_EN_SHIFT_MASK) & (~(1<<ch))))
#define _dmac_set_ch_en(pdmac,ch)                             _reg_modify(pdmac->CHEN,(1<<ch)<<DMAC_CH_WE_EN_SHIFT_MASK, ~(1<<ch))
#define _damc_get_ch_en(pdmac,ch)                             _reg_chk(pdmac->CHEN,(1<<ch))
#define _dmac_set_transfer_length(pdmac,ch, len)              _reg_write(pdmac->CH[ch].CTRL_HIGH, len)
#define _dmac_set_source_address(pdmac,ch, addr)              _reg_write(pdmac->CH[ch].SRCADDR, addr)
#define _dmac_set_destination_address(pdmac,ch, addr)         _reg_write(pdmac->CH[ch].DSTADDR, addr)
#define _dmac_raw_interrupt_en(pdmac,ch)                      _reg_write(pdmac->MASKTFR,((1<<ch)<<8) | (1<<ch))
#define _dmac_raw_interrupt_dis(pdmac,ch)                     _reg_write(pdmac->MASKTFR, (((1<<ch)<<DMAC_CH_WE_EN_SHIFT_MASK))&(~(1<<ch))) //(pdmac->MASKTFR &= ~(((1<<ch)<<8 | (1<<ch))))              
#define _dmac_get_raw_interrupt_en(pdmac,ch)                  (_reg_read(pdmac->MASKTFR )&(1<<ch))
#define _dmac_block_interrupt_en(pdmac,ch)                    (pdmac->MASKBLOCK |= (((1<<ch)<<8 | (1<<ch))))
#define _dmac_block_interrupt_dis(pdmac,ch)                   (pdmac->MASKBLOCK = (pdmac->MASKBLOCK|((1<<ch)<<DMAC_CH_WE_EN_SHIFT_MASK))&(~(1<<ch))) //(pdmac->MASKTFR &= ~(((1<<ch)<<8 | (1<<ch))))              
#define _dmac_get_block_interrupt_en(pdmac,ch)                (_reg_read(pdmac->MASKBLOCK )&(1<<ch))
/*DMA_RAWTFR*/
#define _dmac_get_raw_interrupt_status(pdmac,ch)              (_reg_read(pdmac->RAWTFR)&(1<<ch))
#define _dmac_get_block_interrupt_status(pdmac,ch)            (_reg_read(pdmac->RAWBLOCK)&(1<<ch))
#define _dmac_clr_raw_interrupt_status(pdmac,ch)              (_reg_write(pdmac->CLRTFR, 1<<ch))
#define _dmac_clr_block_interrupt_status(pdmac,ch)            (_reg_write(pdmac->CLRBLOCK, 1<<ch))
#define _dmac_en(pdmac)                                        _bit_set(pdmac->CONFIG,DMAC_EN)
#define _dmac_dis(pdmac)                                       _bit_clr(pdmac->CONFIG,DMAC_EN)
/*CFGn*/
#define _dmac_src_hs_soft(pdmac,ch)                           _bit_set(pdmac->CH[ch].CONFIG,DMAC_HS_SEL_SRC)
#define _dmac_src_hs_hard(pdmac,ch)                           _bit_clr(pdmac->CH[ch].CONFIG,DMAC_HS_SEL_SRC)
#define _dmac_dst_hs_soft(pdmac,ch)                           _bit_set(pdmac->CH[ch].CONFIG,DMAC_HS_SEL_DST)
#define _dmac_dst_hs_hard(pdmac,ch)                           _bit_clr(pdmac->CH[ch].CONFIG,DMAC_HS_SEL_DST)
#define _dmac_ch_set_suspend(pdmac,ch)                        _bit_set(pdmac->CH[ch].CONFIG,DMAC_CH_SUSP)
#define _dmac_ch_clr_suspend(pdmac,ch)                        _bit_clr(pdmac->CH[ch].CONFIG,DMAC_CH_SUSP)
#define _dmac_chk_fifo_empty_status(pdmac,ch)                 _reg_chk(pdmac->CH[ch].CONFIG,DMAC_FIFO_EMPTY)

/*DMA_CTRLn*/
#define _dmac_int_en_en(pdmac,ch)                            _bit_set(pdmac->CH[ch].CTRL,DMAC_INT_EN)
#define _dmac_int_en_dis(pdmac,ch)                           _bit_clr(pdmac->CH[ch].CTRL,DMAC_INT_EN)
#define _dmac_set_dmac_ctrln(pdmac,ch, val)                  _reg_write(pdmac->CH[ch].CTRL, val)
#define _dmac_clr_dmac_ctrln(pdmac,ch)                   		 _reg_write(pdmac->CH[ch].CTRL, 0)
#define _dmac_set_tt_fc(pdmac,ch, tt_fc)                     _reg_modify(pdmac->CH[ch].CTRL, DMAC_TT_FC_BITS_MASK, tt_fc<<DMAC_TT_FC_SHIFT_MASK) 

/*CHG_HIGHn*/
//#define _dmac_set_src_peripheral(pdmac,ch,per) _reg_modify(pdmac->CH[ch].CONFIG_HIGH,DMAC_SRC_PER_BITS_MASK,per<<(DMAC_SRC_PER_SHIFT_MASK))
//#define _dmac_set_dst_peripheral(pdmac,ch,per) _reg_modify(pdmac->CH[ch].CONFIG_HIGH,DMAC_DST_PER_BITS_MASK,per<<(DMAC_DST_PER_SHIFT_MASK))

#define _dmac_set_src_peripheral(pdmac,ch,per)               _reg_write(pdmac->CH[ch].CONFIG_HIGH,per<<(DMAC_SRC_PER_SHIFT_MASK))
#define _dmac_set_dst_peripheral(pdmac,ch,per)               _reg_write(pdmac->CH[ch].CONFIG_HIGH,per<<(DMAC_DST_PER_SHIFT_MASK))

/**
  * @}
  */

/*** 结构体、枚举变量定义 *****************************************************/
#ifdef FILE_OUT
/** @defgroup DRV_DMA_Exported_Types Exported Types
  *
  * @{
  */
#endif

/**
 * @brief DMA 链表结构体定义
 *
 */
typedef struct
{
	__IO uint32_t	src_addr;
	__IO uint32_t	dst_addr;
	__IO uint32_t	next_lli;
	__IO uint32_t	control;
	__IO uint32_t	len;
}DMAC_LLITypeDef;

/**
  * @}
  */

/*** 全局变量声明 **************************************************************/
#ifdef FILE_OUT
/** @defgroup DRV_DMA_Exported_Variables Exported Variables
  *
  * @{
  */
#endif


/**
  * @}
  */

/*** 函数声明 ******************************************************************/
#ifdef FILE_OUT
/** @defgroup DRV_DMA_Exported_Functions Exported Functions
  * @{
  */
#endif
extern void DRV_DMAC_CtrlRegConfig(DMAC_TypeDef *pdmac,uint32_t ch, uint32_t tt_fc, uint32_t src_msize, uint32_t dest_msize, uint32_t sinc, uint32_t dinc, uint32_t src_tr_wideh, uint32_t dst_tr_width);
extern BitActionTypeDef DRV_DMAC_GetRawStatus(DMAC_TypeDef *pdmac,uint32_t ch);
extern void DRV_DMAC_ClearRawStatus(DMAC_TypeDef *pdmac,uint32_t ch);
extern void DRV_DMAC_DisTfrIt(DMAC_TypeDef *pdmac,uint32_t ch);
extern void DRV_DMAC_ClrTrfFlag(DMAC_TypeDef *pdmac,uint32_t ch);
extern void DRV_DMAC_LliRegInit(DMAC_TypeDef *pdmac,uint32_t ch,DMAC_LLITypeDef *pdma_lli);

extern void DMA_REG_Init(uint32_t dmac_base_addr ,uint8_t dma_ch);
extern void dma_ssi_m2p_start(uint8_t* psend, uint8_t* precv, uint32_t length, bool binten);
extern void dma_ssi_wait( bool binten);
extern void dma_ssi_p2m_lli_start(uint8_t* psrc, uint8_t* pread, uint32_t length, bool binten);
extern int  get_dma_flag(bool binten);
extern void clear_dma_flag(bool binten);
/**
  * @}
  */

/**
  *@}
  */

/**
  *@}
  */

#ifdef __cplusplus
}
#endif

#endif /* __DMA_HAL_H */



