#include "periph_dma.h"

TASK_STRUCT SDMA_Task_Struct;
int SDMA_TaskTable[32];

void DMA_Cmd(FunctionalState status)
{
	if(status != DISABLE)
		SYS_CTRL->SDMA_EN = ENABLE;
	else
		SYS_CTRL->SDMA_EN = DISABLE;
}


void DMA_Init(void)
{
	for (int i=0; i<32; i++) {
		SDMA_TaskTable[i] = (uint32_t)(SDMA_Task_Struct.task0 + i*SDMA_TASK_SIZE);
	}
	SYS_CTRL->SDMA_TASK_TABLE_ADDR = (uint32_t)SDMA_TaskTable;
}

void DMA_action(uint8_t dma_action)
{
	SYS_CTRL->SDMA_ACTION = dma_action;
	SYS_CTRL->SDMA_ACTION = 0;	
}

void DMA_Task_Init(SDMA_TASK_InitTypeDef *dma_task_ptr, uint32_t *dma_taskX)
{
	uint32_t t = 0;
	
	// 传输字节设置
	if(dma_task_ptr->DMA_WORD_EN == SDMA_TASK_TRANSACTION_WORD)
		dma_task_ptr->NUM_BYTES = (dma_task_ptr->NUM_BYTES << 2);
	
	t = (dma_task_ptr->DMA_IT_EN) + (dma_task_ptr->DMA_WORD_EN) + (dma_task_ptr->TASK_FORMAT) + (dma_task_ptr->CMD_WAR) +\
		dma_task_ptr->CMD_PRE_EN + (dma_task_ptr->TRIGGER_INDEX << 20) + (dma_task_ptr->SRC_ADD_INC_EN) + (dma_task_ptr->DST_ADD_INC_EN)+\
		(dma_task_ptr->SRC_BEGIN_UPD_EN)+(dma_task_ptr->DST_BEGIN_UPD_EN) + (dma_task_ptr->NUM_BYTES);
	*(volatile uint32_t*)(dma_taskX + 0) = t;
	
	// 源地址
	*(volatile uint32_t*)(dma_taskX+1) = dma_task_ptr->SRC_ADDR;
	
	// 目标地址
	*(volatile uint32_t*)(dma_taskX + 2) = dma_task_ptr->DST_ADDR;
	
	// 传输模式设置 FIFO、COMMAND、 标准模式
	t = 0;
	if(dma_task_ptr->TASK_FORMAT == SDMA_TASK_MODE_FIFO)
	{
		t = t + ((dma_task_ptr->FIFO_MODE_DST) << 0) + ((dma_task_ptr->FIFO_MODE_SRC) << 1);
		t = t + ((dma_task_ptr->FIFO_SIZE) << 4);
	}
	else if(dma_task_ptr->TASK_FORMAT == SDMA_TASK_MODE_COMMAND)
	{
		t = (dma_task_ptr->CMD_ADDR);
	}
    *(volatile uint32_t*)(dma_taskX + 3) = t;
	
	// COMMAND模式配置
	if(dma_task_ptr->TASK_FORMAT == SDMA_TASK_MODE_COMMAND)
		*(volatile uint32_t*)(dma_taskX + 4) = dma_task_ptr -> CMD_WDATA;
	else
	    *(volatile uint32_t*)(dma_taskX + 4) = 0;
		
	if(dma_task_ptr->TASK_FORMAT == SDMA_TASK_MODE_COMMAND)
	    *(volatile uint32_t*)(dma_taskX + 5) = dma_task_ptr -> CMD_MASK;
    else
	    *(volatile uint32_t*)(dma_taskX + 4) = 0;
}

void DMA_task_struct_init(SDMA_TASK_InitTypeDef *sdma_task_ptr)
{
	sdma_task_ptr ->DMA_IT_EN = SDMA_TASK_INTR_DISABLE;
	sdma_task_ptr ->DMA_WORD_EN = SDMA_TASK_TRANSACTION_BYTE;
	sdma_task_ptr ->TASK_FORMAT = SDMA_TASK_MODE_NORMAL;
	sdma_task_ptr ->CMD_WAR = SDMA_TASK_CMD_WAR_DISABLE;
	sdma_task_ptr ->CMD_PRE_EN = SDMA_TASK_CMD_PRE_DISABLE;
	
	
	sdma_task_ptr ->TRIGGER_INDEX = 31;
    sdma_task_ptr ->SRC_ADD_INC_EN = SDMA_TASK_SRC_ADD_INCRE_DISABLE;
    sdma_task_ptr ->DST_ADD_INC_EN = SDMA_TASK_DST_ADD_INCRE_DISABLE;
    sdma_task_ptr ->SRC_BEGIN_UPD_EN = SDMA_TASK_SRC_BEGIN_UDT_DISABLE;
    sdma_task_ptr ->DST_BEGIN_UPD_EN = SDMA_TASK_DST_BEGIN_UDT_DISABLE;
	sdma_task_ptr ->NUM_BYTES = 0;
	sdma_task_ptr ->SRC_ADDR = 0;
	sdma_task_ptr ->DST_ADDR = 0;
	sdma_task_ptr ->CMD_ADDR = 0;
	sdma_task_ptr ->CMD_WDATA = 0;
	sdma_task_ptr ->CMD_MASK = 0;
	sdma_task_ptr ->FIFO_SIZE = 0;
	sdma_task_ptr ->FIFO_MODE_SRC = 0;
	sdma_task_ptr ->FIFO_MODE_DST = 0;
	
}

void DMA_value_set(uint32_t SDMAx, FlagStatus NewStatus)
{
	if(NewStatus == SET)
		SYS_CTRL->SDMA_TASK_VAL |= SDMAx;
	else
		 SYS_CTRL->SDMA_TASK_VAL &= ~(SDMAx);
}

// 所有DMA状态
uint32_t DMA_status(void)
{
	return SYS_CTRL->SDMA_TASK_STATUS;
}

// 某位DMA状态
uint8_t DMA_status_bit(uint32_t SDMAx)
{
	uint8_t flag;
	if((SDMAx & (SYS_CTRL->SDMA_TASK_STATUS)) != 0)
		flag = SET;
	else
		flag = RESET;
	return flag;
}

uint32_t DMA_Get_it_status(void)
{
	return SYS_CTRL->SDMA_INT_STATUS;
}

uint8_t DMA_get_it_status_bit(uint32_t SDMAx)
{
	uint8_t flag;
	if((SDMAx & (SYS_CTRL->SDMA_INT_STATUS)) != 0)
		flag = SET;
	else
		flag = RESET;
	return flag;	
}

void DMA_it_clr(uint32_t SDMAx)
{
	SYS_CTRL->SDMA_INT_CLEAR = SDMAx;
}
