168 lines
5.9 KiB
C
168 lines
5.9 KiB
C
/*
|
|
* 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;
|
|
}
|
|
|
|
|
|
|
|
|