/*
 * memcpy_dma.c
 *
 *  Created on: Oct 1, 2019
 *      Author: abody
 */
#include <f4ll_c/dmahelper.h>
#include <f4ll_c/memcpydma.h>

#ifndef DIAG_INTERRUPT_IN
#	define DIAG_INTERRUPT_IN()
#endif

#ifndef DIAG_INTERRUPT_OUT
#	define DIAG_INTERRUPT_OUT()
#endif

volatile uint8_t g_memcpyDmaBusy = 0;

static struct dmainfo_t g_memcpyDmaInfo;

void Mcd_Init(DMA_TypeDef *dma, uint32_t stream)
{
	Dma_Init(&g_memcpyDmaInfo, dma, stream);
	LL_DMA_EnableIT_TC(dma, stream);
}

void * Mcd_Copy(void *dst, void const *src, size_t length)
{
	LL_DMA_SetM2MSrcAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)src);
	LL_DMA_SetM2MDstAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)dst);
	LL_DMA_SetDataLength(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (length+3)/4 );
	g_memcpyDmaBusy = 1;
	LL_DMA_EnableStream(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream);
	while(g_memcpyDmaBusy);
	return dst;
}

void Mcd_HandleDmaIrq(void)
{
	DIAG_INTERRUPT_IN();
	if(*g_memcpyDmaInfo.isReg & g_memcpyDmaInfo.tcMask) {	// DMA transfer complete
		*g_memcpyDmaInfo.ifcReg = g_memcpyDmaInfo.tcMask;
		LL_DMA_DisableStream(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream);
		g_memcpyDmaBusy = 0;
	}
	DIAG_INTERRUPT_OUT();
}
