/*
 * AS5048A_dma.c
 *
 * Created: 18/07/2021 14:38:25
 *  Author: Nick-XMG
 */ 

#include "AS5048A_dma.h"
#include "atmel_start_pins.h"


static uint8_t AS5048A_rx_buffer[2] = {0};
static uint8_t AS5048A_tx_buffer[2] = {0};


void spi_master_tx_complete_cb(struct _dma_resource *const resource)
{
	//DMAC->Channel[CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
	delay_us(10);
	gpio_set_pin_level(SPI_SS, true);
}

void spi_master_rx_complete_cb(struct _dma_resource *const resource)
{
	//DMAC->Channel[CONF_SERCOM_6_RECEIVE_DMA_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
	gpio_set_pin_level(SPI_SS, true);
	
}

void as5048a_init(void)
{
	spi_m_dma_enable(&SPI_0);
	/* tx_descriptor */
	DmacDescriptor tx_descriptor;
	tx_descriptor.DSTADDR.reg = (uint32_t)&AS5048A_SPI->SPI.DATA.reg;							// destination address is SPI DATA register
	tx_descriptor.SRCADDR.reg = (uint32_t)(AS5048A_tx_buffer + sizeof AS5048A_tx_buffer);   // source address is the DMA buffer
	tx_descriptor.DESCADDR.reg = 0;															// only one transfer descriptor
	tx_descriptor.BTCTRL.bit.BEATSIZE = DMAC_BTCTRL_BEATSIZE_BYTE_Val;						// beat size is one byte
	tx_descriptor.BTCTRL.bit.DSTINC = 0;													// destination address increment disabled
	tx_descriptor.BTCTRL.bit.SRCINC = 1;													// source address increment enabled
	tx_descriptor.BTCTRL.bit.STEPSEL = DMAC_BTCTRL_STEPSEL_SRC_Val;							// flexible source address increment size
	tx_descriptor.BTCTRL.bit.STEPSIZE = DMAC_BTCTRL_STEPSIZE_X1_Val;						// source address increment is one byte
	tx_descriptor.BTCTRL.bit.BLOCKACT = DMAC_BTCTRL_BLOCKACT_NOACT_Val;						// request interrupt at end of block transfer
	tx_descriptor.BTCNT.reg = sizeof AS5048A_tx_buffer;											// beat count
	tx_descriptor.BTCTRL.bit.VALID = 1;
	
	//DMA_add_channel(0x0D, tx_descriptor, 1);
	
	/* Register Callback */
	spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_TX_DONE, spi_master_tx_complete_cb);
	//struct _dma_resource *resource_tx;
	//_dma_get_channel_resource(&resource_tx, CONF_SERCOM_6_TRANSMIT_DMA_CHANNEL);
	//resource_tx->dma_cb.transfer_done = DMAC_Handler_tx_cb;
	
	/* rx_descriptor */
	DmacDescriptor rx_descriptor;
	rx_descriptor.DSTADDR.reg = (uint32_t)(AS5048A_rx_buffer + sizeof AS5048A_rx_buffer);							// destination address is SPI DATA register
	rx_descriptor.SRCADDR.reg = (uint32_t)&AS5048A_SPI->SPI.DATA.reg;   // source address is the DMA buffer
	rx_descriptor.DESCADDR.reg = 0;															// only one transfer descriptor
	rx_descriptor.BTCTRL.bit.BEATSIZE = DMAC_BTCTRL_BEATSIZE_BYTE_Val;						// beat size is one byte
	rx_descriptor.BTCTRL.bit.DSTINC = 0;													// destination address increment disabled
	rx_descriptor.BTCTRL.bit.SRCINC = 1;													// source address increment enabled
	rx_descriptor.BTCTRL.bit.STEPSEL = DMAC_BTCTRL_STEPSEL_SRC_Val;							// flexible source address increment size
	rx_descriptor.BTCTRL.bit.STEPSIZE = DMAC_BTCTRL_STEPSIZE_X1_Val;						// source address increment is one byte
	rx_descriptor.BTCTRL.bit.BLOCKACT = DMAC_BTCTRL_BLOCKACT_NOACT_Val;						// request interrupt at end of block transfer
	rx_descriptor.BTCNT.reg = sizeof AS5048A_rx_buffer;											// beat count
	rx_descriptor.BTCTRL.bit.VALID = 1;
		
	//DMA_add_channel(0x0C, rx_descriptor, 0);
	
	/* Register Callback */
	
	
	spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_RX_DONE, spi_master_rx_complete_cb);
	//struct _dma_resource *resource_rx;
	//_dma_get_channel_resource(&resource_tx, CONF_SERCOM_6_RECEIVE_DMA_CHANNEL);
	//resource_tx->dma_cb.transfer_done = DMAC_Handler_rx_cb;
	
	//DMA_enable();
	
}

uint16_t as5048a_read(uint16_t registerAddress)
{
	uint8_t in_buf[2], out_buf[2];

	volatile uint16_t command = 0b0100000000000000; // PAR=0 R/W=R
	command = command | registerAddress;

	//Add a parity bit on the the MSB
	command |= ((uint16_t)spiCalcEvenParity(command)<<15);
	
	//Split the command into two bytes
	AS5048A_tx_buffer[1] = command & 0xFF;
	AS5048A_tx_buffer[0] = ( command >> 8 ) & 0xFF;
	
	gpio_set_pin_level(SPI_SS, false);
	spi_m_dma_transfer(&SPI_0, AS5048A_tx_buffer, AS5048A_rx_buffer, sizeof AS5048A_tx_buffer );
	//gpio_set_pin_level(SPI_SS, false);
	//_dma_enable_transaction(0,false);
	//_dma_enable_transaction(1,false);
	
	if (AS5048A_rx_buffer[1] & 0x40) {
		int i = 0;
		//as5048a.errorFlag = 1;
	} else {
		//as5048a.errorFlag = 0;
	}
	return (( ( AS5048A_rx_buffer[1] & 0xFF ) << 8 ) | ( AS5048A_rx_buffer[0] & 0xFF )) & ~0xC000;

}

void as5048a_write(void)
{

}

uint8_t calcEvenParity(uint16_t value)
{
	uint8_t cnt = 0;
	uint8_t i;
	for (i = 0; i < 16; i++)
	{
		if (value & 0x1)
		{
			cnt++;
		}
		value >>= 1;
	}
	return cnt & 0x1;
}

void DMA_add_channel(const int trigger_source, DmacDescriptor descriptor, const uint8_t channel)
{
	/* disable DMA if enabled */
	if (DMAC->CTRL.bit.DMAENABLE)
	DMAC->CTRL.bit.DMAENABLE = 0;
	while (DMAC->CTRL.bit.DMAENABLE);
	
	
	_dma_set_descriptor(channel, descriptor);
	
	/* add transfer descriptor to transfer descriptor section (before enabling channel!) */
	//memcpy(descriptor_section + channel * sizeof(DmacDescriptor) , descriptor, sizeof(DmacDescriptor));
	
	/* configure and enable first least significant free channel */
									  // use first free channel
	DMAC->Channel[channel].CHPRILVL.bit.PRILVL = 0x00;                                         // channel priority level 0
	DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = 0x02;                              // one trigger each beat transfer
	DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = trigger_source;                    // select trigger source
	DMAC->Channel[channel].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;                      // enable channel
	
	/* enable DMA block transfer complete interrupt */
	DMAC->Channel[channel].CHINTENSET.bit.TCMPL = 1;                                 // enable DMA block transfer complete interrupt
	NVIC_EnableIRQ(DMAC_1_IRQn);
	
}

void DMA_enable(void)
{
	/* enable DMA controller */
	DMAC->CTRL.bit.DMAENABLE = 1;
}




