#include "drv_dma.h"
#include "drv_clk.h"
#include "drv_misc.h"
#include "kit_time.h"
#include "kit_debug.h"

#define DMA_IT_TC                          ((uint32_t)0x00000002)
#define DMA_IT_HT                          ((uint32_t)0x00000004)
#define DMA_IT_TE                          ((uint32_t)0x00000008)
#define DMA_CCR_EN                         ((uint32_t)0x00000001)
#define DMA1_IT_TE2                        ((uint32_t)0x00000080)
#define DMA1_IT_TC2                        ((uint32_t)0x00000020)
#define DMA_Mode_Normal                    ((uint32_t)0x00000000)
#define DMA_Mode_Circular                  ((uint32_t)0x00000020)
#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)
#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)
#define DMA_MemoryDataSize_Byte            ((uint32_t)0x00000000)
#define DMA_MemoryDataSize_HalfWord        ((uint32_t)0x00000400)
#define DMA_MemoryDataSize_Word            ((uint32_t)0x00000800)
#define DMA_PeripheralDataSize_Byte        ((uint32_t)0x00000000)
#define DMA_PeripheralDataSize_HalfWord    ((uint32_t)0x00000100)
#define DMA_PeripheralDataSize_Word        ((uint32_t)0x00000200)


#define DMA_STREAM3_IT_ERR                 ((uint32_t)0x03400000)
#define DMA_STREAM3_IT_FLAG                ((uint32_t)0x0F400000)

extern volatile uint8_t dma_tx_busy;
extern volatile uint8_t current_buffer;

typedef enum
{
    kDmaIdx_0,
    kDmaIdx_1,
    kDmaIdx_End,
}DmaIdx;

typedef struct
{
    uint8_t             irq;
    uint8_t             ch_id;          //通道实际编号,如通道5编号为4
    DmaIdx              dma_idx;    
    DMA_Stream_TypeDef  *channel_reg;
}Stm32DmaProp;



static KitIrqCall dma_irq_call[kDmaStream_End];
const DMA_TypeDef * dma_array[kDmaIdx_End] = {DMA1, DMA2};
static const Stm32DmaProp stm32_dma[kDmaStream_End] = 
{
    {DMA1_Stream0_IRQn, 0, kDmaIdx_0,  DMA1_Stream0},
    {DMA1_Stream1_IRQn, 1, kDmaIdx_0,  DMA1_Stream1},
    {DMA1_Stream2_IRQn, 2, kDmaIdx_0,  DMA1_Stream2},
    {DMA1_Stream3_IRQn, 3, kDmaIdx_0,  DMA1_Stream3},
    {DMA1_Stream4_IRQn, 4, kDmaIdx_0,  DMA1_Stream4},
    {DMA1_Stream5_IRQn, 5, kDmaIdx_0,  DMA1_Stream5},
    {DMA1_Stream6_IRQn, 6, kDmaIdx_0,  DMA1_Stream6},
    {DMA1_Stream7_IRQn, 7, kDmaIdx_0,  DMA1_Stream7},
   
    {DMA2_Stream0_IRQn, 0, kDmaIdx_1,  DMA2_Stream0},
    {DMA2_Stream1_IRQn, 1, kDmaIdx_1,  DMA2_Stream1},
    {DMA2_Stream2_IRQn, 2, kDmaIdx_1,  DMA2_Stream2},
    {DMA2_Stream3_IRQn, 3, kDmaIdx_1,  DMA2_Stream3},
    {DMA2_Stream4_IRQn, 4, kDmaIdx_1,  DMA2_Stream4},
    {DMA2_Stream5_IRQn, 5, kDmaIdx_1,  DMA2_Stream5},
    {DMA2_Stream6_IRQn, 6, kDmaIdx_1,  DMA2_Stream6},
    {DMA2_Stream7_IRQn, 6, kDmaIdx_1,  DMA2_Stream7},
};


#define DMA1_Channel1_IT_Mask    ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1))
void dma_reset(DmaStream stream_idx)
{
    DMA_Stream_TypeDef* DMAy_Streamx = stm32_dma[stream_idx].channel_reg;
    DMAy_Streamx->CR &= (uint16_t)(~DMA_SxCR_EN);
    /* Reset DMAy Channelx control register */
    DMAy_Streamx->CR  = 0;

    /* Reset DMAy Channelx remaining bytes register */
    DMAy_Streamx->NDTR = 0;

    /* Reset DMAy Channelx peripheral address register */
    DMAy_Streamx->PAR  = 0;

    /* Reset DMAy Channelx memory address register */
    DMAy_Streamx->M0AR = 0;
    DMAy_Streamx->M1AR = 0;
    DMAy_Streamx->FCR = (uint32_t)0x00000021; 
}


const uint32_t dma_clk_en[kDmaIdx_End] = {RCC_AHB1ENR_DMA1EN, RCC_AHB1ENR_DMA2EN};
kit_ret_e drv_dma_init(DmaStream stream_idx, DmaChannel channel, uint32_t dma_config, uint32_t addr)
{    
    uint32_t reg = 0;
    kit_ret_e res = kKit_Ret_Ok;
    KIT_ASSERT_PARAM((stream_idx < kDmaStream_End) && (addr != NULL));  
    
	if((stream_idx < kDmaStream_End) && (addr != NULL))
	{
        RCC->AHB1ENR |= dma_clk_en[stm32_dma[stream_idx].dma_idx]; //开启时钟
        
		//dma初始化
		dma_reset(stream_idx);

		if((dma_config & DMA_CFG_DATA_DIR_M2P) == DMA_CFG_DATA_DIR_M2P)
		{
			reg |= KIT_BIT_MASK_32(6);
		}
        else if((dma_config & DMA_CFG_DATA_DIR_M2M) == DMA_CFG_DATA_DIR_M2M)
		{
			reg |= KIT_BIT_MASK_32(7);
		}
		   
		if((dma_config & DMA_CFG_CYCLE_EXE) == DMA_CFG_CYCLE_EXE)
		{
			reg |= KIT_BIT_MASK_32(8);
		}

		if((dma_config & DMA_CFG_DATA_P_I) == DMA_CFG_DATA_P_I)
		{
			reg |= KIT_BIT_MASK_32(9);
		}
		
		if((dma_config & DMA_CFG_DATA_M_I) == DMA_CFG_DATA_M_I)
		{
			reg |= KIT_BIT_MASK_32(10);
		}
		
		if((dma_config & DMA_CFG_DATA_LEN_2B) == DMA_CFG_DATA_LEN_2B)
		{
			reg |= (KIT_BIT_MASK_32(11) | KIT_BIT_MASK_32(13));
		}
		else if((dma_config & DMA_CFG_DATA_LEN_4B) == DMA_CFG_DATA_LEN_4B)
		{
			reg |= (KIT_BIT_MASK_32(12) | KIT_BIT_MASK_32(14));
		}

        reg |= ((uint32_t)channel) << 25;
		stm32_dma[stream_idx].channel_reg->CR |= reg;
		stm32_dma[stream_idx].channel_reg->PAR = addr;
	}
	else
	{
		res = kKit_Ret_ParamErr;
	}
   
	return res;
}

void drv_dma_set_interrupt(DmaStream stream_idx, uint8_t priority,  KitIrqCall call)
{
    KIT_ASSERT_PARAM(stream_idx < kDmaStream_End);
    
    stm32_dma[stream_idx].channel_reg->CR |= (DMA_SxCR_TCIE | DMA_SxCR_TEIE);
    drv_misc_set_nvic(stm32_dma[stream_idx].irq, priority);
    dma_irq_call[stream_idx] = call;
}

__IO uint32_t * dma_ifcr[4] = {&DMA1->LIFCR, &DMA1->HIFCR, &DMA2->LIFCR, &DMA2->HIFCR};
const uint32_t dma_ifcr_clr_bit[4] = {0x0000003D, 0x00000F40, 0x003D0000, 0x0F400000};
//传输错误或者结束标志位
__IO uint32_t * dma_isr[4] = {&DMA1->LISR, &DMA1->HISR, &DMA2->LISR, &DMA2->HISR};
const uint32_t dma_isr_transfer_end_bit[4] = {0x0000002C, 0x00000B00, 0x002C0000, 0x0B000000};
void drv_dma_set_buf(DmaStream stream_idx,uint8_t* buf, uint16_t len)
{
    DMA_Stream_TypeDef * stream_reg;
    
    KIT_ASSERT_PARAM((buf != NULL) && (len > 0));
    KIT_ASSERT_PARAM(stream_idx < kDmaStream_End);
    
    if((stream_idx < kDmaStream_End) && (buf != NULL))
    {
        stream_reg = stm32_dma[stream_idx].channel_reg;
        //清除标志位
        *dma_ifcr[stream_idx / 4] |= dma_ifcr_clr_bit[stream_idx % 4];
        
        stream_reg->NDTR = len;
        stream_reg->M0AR = (uint32_t)buf;
        
        stream_reg->CR |= DMA_CCR_EN;
    }

}


kit_ret_e drv_dma_send(DmaStream dma_tx_ch, uint8_t *tx_buf, uint16_t tx_len)
{
    uint32_t dly = 0;
    kit_ret_e res = kKit_Ret_Ok;
    
    KIT_ASSERT_PARAM((tx_buf != NULL) && (tx_len > 0));

    drv_dma_set_buf(dma_tx_ch, tx_buf, tx_len);

    //等待接收完成   
    while((*dma_isr[dma_tx_ch >> 2] & dma_isr_transfer_end_bit[dma_tx_ch % 4]) == 0)
    {
        kit_time_dly_ms(1);
        if(++dly > 500)
        {
            res = kKit_Ret_TimeOut;
            break;
        }        
    }
    
    stm32_dma[dma_tx_ch].channel_reg->CR &= ~DMA_CCR_EN ; //关闭DMA通道2
    
    return res;
}

kit_ret_e drv_dma_receive(DmaStream dma_rx_ch, DmaStream dma_tx_ch, uint8_t *rx_buf, uint16_t rx_len)
{
    uint32_t dly = 0;
    kit_ret_e res = kKit_Ret_Ok;
    
    KIT_ASSERT_PARAM(timeout > 0);
    KIT_ASSERT_PARAM(((tx_buf != NULL) && (tx_len > 0)) || ((tx_buf == NULL) && (tx_len == 0)));
    KIT_ASSERT_PARAM(((rx_buf != NULL) && (rx_len > 0)) || ((rx_buf == NULL) && (rx_len == 0)));
    
    drv_dma_set_buf(dma_rx_ch, rx_buf, rx_len);
    drv_dma_set_buf(dma_tx_ch, rx_buf, rx_len);

    //等待接收完成   
    while((*dma_isr[dma_rx_ch >> 2] & dma_isr_transfer_end_bit[dma_rx_ch % 4]) == 0)
    {
        kit_time_dly_ms(1);
        if(++dly > 200)
        {
            res = kKit_Ret_TimeOut;
            break;
        }        
    }
    stm32_dma[dma_tx_ch].channel_reg->CR &= ~DMA_CCR_EN ; //关闭DMA通道3
    stm32_dma[dma_tx_ch].channel_reg->CR &= ~DMA_CCR_EN ; //关闭DMA通道2
    
    return res;
}


void DMA1_Stream0_IRQHandler(void)
{
}

void DMA1_Stream1_IRQHandler(void)
{
}

void DMA1_Stream2_IRQHandler(void)
{
}

void DMA1_Stream3_IRQHandler(void)
{
    kit_ret_e res = kKit_Ret_Ok;
    
    DMA1_Stream3->CR &= ~DMA_CCR_EN ;   //关闭DMA通道2
    DMA1_Stream4->CR &= ~DMA_CCR_EN ;   //关闭DMA通道3
    
    if((DMA1->LISR & DMA_STREAM3_IT_ERR) != 0)
    {
        KIT_ASSERT_RES(0, kKit_Ret_Error);
        res = kKit_Ret_Error;
    }      
    DMA1->LIFCR = DMA_STREAM3_IT_FLAG; //清楚标志位

    if(dma_irq_call[kDma1Stream_3] != NULL)
        dma_irq_call[kDma1Stream_3](res, NULL);
}

void DMA1_Stream4_IRQHandler(void)
{
}

void DMA1_Stream5_IRQHandler(void)
{
}

void DMA1_Stream6_IRQHandler(void)
{
    __disable_irq(); 
    
    if (DMA1->HISR & DMA_HISR_TCIF6) 
		{
        DMA1->HIFCR |= DMA_HIFCR_CTCIF6;
        dma_tx_busy = 0;
        USART2->CR3 &= ~USART_CR3_DMAT;
        
        if (current_buffer == 1) 
				{
            current_buffer = 0;
        }
    }
    else if (DMA1->HISR & DMA_HISR_TEIF6) 
		{
        DMA1->HIFCR |= DMA_HIFCR_CTEIF6;
        dma_tx_busy = 0;
        current_buffer = 0;
    }
    
    __enable_irq();
}

void DMA1_Channel6_IRQHandler(void)
{
}

void DMA2_Stream0_IRQHandler(void)
{
}

void DMA2_Stream1_IRQHandler(void)
{
}

void DMA2_Stream2_IRQHandler(void)
{
}

void DMA2_Stream3_IRQHandler(void)
{
}

void DMA2_Stream4_IRQHandler(void)
{
}

void DMA2_Stream5_IRQHandler(void)
{
}

void DMA2_Stream6_IRQHandler(void)
{
}

void DMA2_Stream7_IRQHandler(void)
{
}

