thesis_bldc_controller/Examples/AS5048A_test/AS5048A_test/AS5048A_dma.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;
}