Got Master/Slave Comms working
This commit is contained in:
@@ -6,8 +6,6 @@
|
||||
*/
|
||||
#include "A1335.h"
|
||||
|
||||
|
||||
|
||||
//--- Normal Write Registers ---//
|
||||
#define EWA (0x02U) // Extended Write Address
|
||||
#define EWD (0x04U) // Extended Write Data
|
||||
@@ -25,11 +23,14 @@
|
||||
#define ERM (0x34U) // Device error status masking
|
||||
#define XERM (0x36U) // Extended error status masking
|
||||
|
||||
const uint32_t WRITE = 0x40;
|
||||
const uint32_t READ = 0x00;
|
||||
const uint32_t COMMAND_MASK = 0xC0;
|
||||
const uint32_t ADDRESS_MASK = 0x3F;
|
||||
|
||||
//--- Extended Write Registers ---//
|
||||
#define ORATE (0xFFD0) // Output Rate
|
||||
|
||||
//--- Errors ---//
|
||||
|
||||
#define kNOERROR 0
|
||||
#define kPRIMARYREADERROR 1
|
||||
#define kEXTENDEDREADTIMEOUTERROR 2
|
||||
@@ -38,23 +39,11 @@
|
||||
#define kCRCERROR 5
|
||||
#define kUNABLETOCHANGEPROCESSORSTATE 6
|
||||
|
||||
const uint16_t ChipSelectPin = 5;
|
||||
const uint16_t LEDPin = 13;
|
||||
bool debugPrint = true;
|
||||
|
||||
const uint32_t WRITE = 0x40;
|
||||
const uint32_t READ = 0x00;
|
||||
const uint32_t COMMAND_MASK = 0xC0;
|
||||
const uint32_t ADDRESS_MASK = 0x3F;
|
||||
|
||||
unsigned long nextTime;
|
||||
bool ledOn = false;
|
||||
bool includeCRC = false;
|
||||
|
||||
bool debugPrint = false;
|
||||
|
||||
struct SPI_S A1 = {
|
||||
.SPI_angleSensor_n = NULL,
|
||||
.io = NULL,
|
||||
struct SPI_A1335 A1 = {
|
||||
.SPI_descr = NULL,
|
||||
.io_descr = NULL,
|
||||
.state = 0,
|
||||
.SS_pin = Angle_SS,
|
||||
.tx_buffer = NULL,
|
||||
@@ -62,13 +51,17 @@ struct SPI_S A1 = {
|
||||
|
||||
};
|
||||
|
||||
void angleSensor_init(struct spi_m_sync_descriptor *spi, struct SPI_S *Sn)
|
||||
void a1335_init(struct spi_m_sync_descriptor *spi, struct SPI_A1335 *Sn)
|
||||
{
|
||||
Sn->SPI_angleSensor_n = spi;
|
||||
spi_m_sync_get_io_descriptor(Sn->SPI_angleSensor_n, &Sn->io);
|
||||
spi_m_sync_enable(Sn->SPI_angleSensor_n);
|
||||
Sn->SPI_descr = spi;
|
||||
// Set Mode 3 : CPOL = 1; CPHA = 1;
|
||||
hri_sercomspi_write_CTRLA_CPOL_bit(spi->dev.prvt, true);
|
||||
hri_sercomspi_write_CTRLA_CPHA_bit(spi->dev.prvt, true);
|
||||
//Get IO descriptor
|
||||
spi_m_sync_get_io_descriptor(Sn->SPI_descr, &Sn->io_descr);
|
||||
spi_m_sync_enable(Sn->SPI_descr);
|
||||
gpio_set_pin_level(Sn->SS_pin, true);
|
||||
if(Sn->io == NULL || Sn->SPI_angleSensor_n == NULL)
|
||||
if(Sn->io_descr == NULL || Sn->SPI_descr == NULL)
|
||||
{
|
||||
Sn->state = 4;
|
||||
} else {
|
||||
@@ -76,7 +69,7 @@ void angleSensor_init(struct spi_m_sync_descriptor *spi, struct SPI_S *Sn)
|
||||
}
|
||||
}
|
||||
|
||||
void angleSensor_State_Machine(struct SPI_S *Sn)
|
||||
void a1335_State_Machine(struct SPI_A1335 *Sn)
|
||||
{
|
||||
volatile uint16_t angle;
|
||||
switch(Sn->state){
|
||||
@@ -85,19 +78,8 @@ void angleSensor_State_Machine(struct SPI_S *Sn)
|
||||
case 1: // State After angleSensor_init. Configure Sensor
|
||||
Sn->state++;
|
||||
break;
|
||||
case 2: // Syncronouse blocking read
|
||||
PrimaryRead(Sn, 0x20, &angle);
|
||||
if (CalculateParity(angle))
|
||||
{
|
||||
volatile float read_angle = (float)(angle & 0x0FFF) * 360.0 / 4096.0;
|
||||
printf("Angle = ");
|
||||
printf("%f", read_angle);
|
||||
printf(" Degrees\n\r");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Parity error on Angle read\n\r");
|
||||
}
|
||||
case 2: // Synchronous blocking read
|
||||
a1335_getRotationInDegrees(Sn);
|
||||
break;
|
||||
case 3: // Continuously Read Angle (DMA)
|
||||
break;
|
||||
@@ -106,6 +88,44 @@ void angleSensor_State_Machine(struct SPI_S *Sn)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getRawRotation
|
||||
*
|
||||
* Read Raw Angle Register Value
|
||||
*/
|
||||
uint16_t a1335_getRawRotation(struct SPI_A1335 *Sn)
|
||||
{
|
||||
uint16_t rawAngle;
|
||||
PrimaryRead(Sn, ANG, &rawAngle);
|
||||
return rawAngle;
|
||||
}
|
||||
|
||||
/*
|
||||
* getRotationInDegrees
|
||||
*
|
||||
* Read angle register and return angle in Degrees
|
||||
*/
|
||||
float a1335_getRotationInDegrees(struct SPI_A1335 *Sn)
|
||||
{
|
||||
uint16_t rawAngle = a1335_getRawRotation(Sn);
|
||||
float angleDegrees;
|
||||
if (CalculateParity(rawAngle))
|
||||
{
|
||||
angleDegrees = (float)(rawAngle & 0x0FFF) * 360.0 / 4096.0;
|
||||
if (debugPrint)
|
||||
{
|
||||
printf("Angle = ");
|
||||
printf("%f", angleDegrees);
|
||||
printf(" Degrees\n\r");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Parity error on Angle read\n\r");
|
||||
}
|
||||
return angleDegrees;
|
||||
}
|
||||
|
||||
/*
|
||||
* CalculateParity
|
||||
*
|
||||
@@ -166,7 +186,7 @@ uint8_t CalculateCRC(uint16_t input)
|
||||
*
|
||||
* Read from the primary serial registers
|
||||
*/
|
||||
uint16_t PrimaryRead(struct SPI_S *Sn, uint16_t address, uint16_t* value)
|
||||
uint16_t PrimaryRead(struct SPI_A1335 *Sn, uint16_t address, uint16_t* value)
|
||||
{
|
||||
|
||||
uint8_t in_buf[2], out_buf[2];
|
||||
@@ -177,11 +197,12 @@ uint16_t PrimaryRead(struct SPI_S *Sn, uint16_t address, uint16_t* value)
|
||||
out_buf[1] = command & 0xFF;
|
||||
out_buf[0] = ( command >> 8 ) & 0xFF;
|
||||
gpio_set_pin_level(Sn->SS_pin, false);
|
||||
transfer16(Sn, command);
|
||||
a1335_transfer16(Sn, command);
|
||||
gpio_set_pin_level(Sn->SS_pin, true);
|
||||
|
||||
|
||||
/* Send again to Get Response */
|
||||
gpio_set_pin_level(Sn->SS_pin, false);
|
||||
returnedVal = transfer16(Sn, command);
|
||||
returnedVal = a1335_transfer16(Sn, command);
|
||||
gpio_set_pin_level(Sn->SS_pin, true);
|
||||
|
||||
// printf("In_buff= ");
|
||||
@@ -200,7 +221,7 @@ uint16_t PrimaryRead(struct SPI_S *Sn, uint16_t address, uint16_t* value)
|
||||
|
||||
return kNOERROR;
|
||||
}
|
||||
|
||||
|
||||
uint16_t a1335_transfer16(struct SPI_A1335 *Sn, uint16_t value)
|
||||
{
|
||||
uint8_t in_buf[2], out_buf[2];
|
||||
@@ -211,12 +232,11 @@ uint16_t transfer16(struct SPI_S *Sn, uint16_t value)
|
||||
struct spi_xfer xfer;
|
||||
xfer.rxbuf = in_buf;
|
||||
xfer.txbuf = (uint8_t *)out_buf;
|
||||
xfer.size = 2;
|
||||
xfer.size = 2;
|
||||
spi_m_sync_transfer(Sn->SPI_descr, &xfer);
|
||||
wordRead = (uint16_t)((in_buf[0] << 8) | in_buf[1]);
|
||||
return wordRead;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PrimaryWrite
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#define A1335_H_
|
||||
#include <atmel_start.h>
|
||||
|
||||
struct SPI_S {
|
||||
struct spi_m_sync_descriptor *SPI_angleSensor_n;
|
||||
struct io_descriptor *io;
|
||||
struct SPI_A1335 {
|
||||
struct spi_m_sync_descriptor *SPI_descr;
|
||||
struct io_descriptor *io_descr;
|
||||
uint8_t state;
|
||||
uint32_t SS_pin;
|
||||
struct spi_xfer xfer;
|
||||
@@ -20,22 +20,26 @@ struct SPI_S {
|
||||
uint8_t *rx_buffer;
|
||||
};
|
||||
|
||||
struct SPI_S A1;
|
||||
struct SPI_A1335 A1;
|
||||
struct io_descriptor *io;
|
||||
|
||||
void angleSensor_init(struct spi_m_sync_descriptor *spi, struct SPI_S *Sn);
|
||||
void angleSensor_State_Machine(struct SPI_S *Sn);
|
||||
void a1335_init(struct spi_m_sync_descriptor *spi, struct SPI_A1335 *Sn);
|
||||
void a1335_State_Machine(struct SPI_A1335 *Sn);
|
||||
|
||||
bool CalculateParity(uint16_t input);
|
||||
uint8_t CalculateCRC(uint16_t input);
|
||||
uint16_t PrimaryRead(struct SPI_S *Sn, uint16_t address, uint16_t* value);
|
||||
uint16_t PrimaryRead(struct SPI_A1335 *Sn, uint16_t address, uint16_t* value);
|
||||
uint16_t PrimaryWrite(uint16_t cs, uint16_t address, uint16_t value);
|
||||
uint16_t ExtendedRead(uint16_t cs, uint16_t address, uint32_t value);
|
||||
uint16_t ExtendedWrite(uint16_t cs, uint16_t address, uint32_t value);
|
||||
uint16_t SetProcessorStateToRun(uint8_t cs);
|
||||
uint16_t SetProcessorStateToIdle(uint8_t cs);
|
||||
uint16_t SetProcessorStateToRun(uint8_t cs);
|
||||
uint16_t transfer16(struct SPI_S *Sn, uint16_t value);
|
||||
bool CalculateParity(uint16_t input);
|
||||
uint8_t CalculateCRC(uint16_t input);
|
||||
uint16_t a1335_transfer16(struct SPI_A1335 *Sn, uint16_t value);
|
||||
|
||||
uint16_t a1335_getRawRotation(struct SPI_A1335 *Sn);
|
||||
float a1335_getRotationInDegrees(struct SPI_A1335 *Sn);
|
||||
uint16_t getErrors(void);
|
||||
|
||||
|
||||
#endif /* A1335_H_ */
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* AS5048.c
|
||||
*
|
||||
* Created: 27/07/2021 16:13:20
|
||||
* Author: Nick-XMG
|
||||
*/
|
||||
|
||||
#include "AS5048.h"
|
||||
|
||||
#define AS5048A_CMD_NOP (0x0000)
|
||||
#define AS5048A_READ (0x4000)
|
||||
#define AS5048A_CLEAR_ERROR_FLAG (0x0001)
|
||||
#define AS5048A_PROGRAMMING_CONTROL (0x0003)
|
||||
#define AS5048A_OTP_REGISTER_ZERO_POS_HIGH (0x0016)
|
||||
#define AS5048A_OTP_REGISTER_ZERO_POS_LOW (0x0017)
|
||||
#define AS5048A_DIAG_AGC (0x3FFD)
|
||||
#define AS5048A_MAGNITUDE (0x3FFE)
|
||||
#define AS5048A_ANGLE (0x3FFF)
|
||||
|
||||
|
||||
#define AS5048A_MAX_VALUE (8191.0f)
|
||||
|
||||
static bool debugPrint = true;
|
||||
|
||||
struct SPI_AS5048 AS_1 = {
|
||||
.SPI_descr = NULL,
|
||||
.io_descr = NULL,
|
||||
.flags = 0,
|
||||
.state = 0,
|
||||
.SS_pin = Angle_SS,
|
||||
.tx_buffer = NULL,
|
||||
.rx_buffer = NULL,
|
||||
|
||||
};
|
||||
|
||||
void as5048a_State_Machine(struct SPI_AS5048 *Sn)
|
||||
{
|
||||
volatile uint16_t angle;
|
||||
switch(Sn->state) {
|
||||
case 0: // Default un-initialized State
|
||||
break;
|
||||
case 1: // State After angleSensor_init. Configure Sensor
|
||||
Sn->state++;
|
||||
break;
|
||||
case 2: // Synchronous blocking read
|
||||
as5048a_getRotationInDegrees(Sn);
|
||||
break;
|
||||
case 3: // Continuously Read Angle (DMA)
|
||||
break;
|
||||
case 4: // Error State
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void as5048a_init(struct spi_m_sync_descriptor *spi, struct SPI_AS5048 *Sn)
|
||||
{
|
||||
Sn->SPI_descr = spi;
|
||||
spi_m_sync_disable(&SPI_1);
|
||||
|
||||
// Set Mode 1 : CPOL = 0; CPHA = 1;
|
||||
hri_sercomspi_write_CTRLA_CPOL_bit(&SPI_1, false);
|
||||
hri_sercomspi_write_CTRLA_CPHA_bit(&SPI_1, true);
|
||||
|
||||
//Get IO descriptor
|
||||
spi_m_sync_get_io_descriptor(Sn->SPI_descr, &Sn->io_descr);
|
||||
spi_m_sync_enable(&SPI_1);
|
||||
gpio_set_pin_level(Sn->SS_pin, true);
|
||||
if(Sn->io_descr == NULL || Sn->SPI_descr == NULL) {
|
||||
Sn->state = 4;
|
||||
} else {
|
||||
Sn->state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t as5048a_read(struct SPI_AS5048 *Sn, uint16_t address)
|
||||
{
|
||||
uint8_t in_buf[2], out_buf[2];
|
||||
uint16_t returnedVal;
|
||||
|
||||
volatile uint16_t command = 0b0100000000000000; // PAR=0 R/W=R
|
||||
command = command | address;
|
||||
|
||||
//Add a parity bit on the the MSB
|
||||
command |= ((uint16_t)as5048a_CalcEvenParity(command)<<15);
|
||||
|
||||
//Split the command into two bytes
|
||||
out_buf[1] = command & 0xFF;
|
||||
out_buf[0] = ( command >> 8 ) & 0xFF;
|
||||
|
||||
/* Send Command */
|
||||
gpio_set_pin_level(Sn->SS_pin, false);
|
||||
as5048a_transfer16(Sn, command);
|
||||
gpio_set_pin_level(Sn->SS_pin, true);
|
||||
|
||||
/* Send again to Get Response */
|
||||
gpio_set_pin_level(Sn->SS_pin, false);
|
||||
returnedVal = as5048a_transfer16(Sn, command);
|
||||
gpio_set_pin_level(Sn->SS_pin, true);
|
||||
|
||||
// printf("In_buff= ");
|
||||
// /* Print Received data by SPI Master from SPI Slave on Console */
|
||||
// for (int i = 0; i < 2; i++) {
|
||||
// printf("%u", in_buf[i]);
|
||||
// }
|
||||
// printf("\n\r");
|
||||
if(debugPrint) {
|
||||
printf("Returned val = %u \n\r", returnedVal);
|
||||
}
|
||||
|
||||
|
||||
if (returnedVal & 0x4000) {
|
||||
Sn->flags = 1;
|
||||
} else {
|
||||
Sn->flags = 0;
|
||||
}
|
||||
|
||||
//Return the data, stripping the parity and error bits
|
||||
return (( ( in_buf[1] & 0xFF ) << 8 ) | ( in_buf[0] & 0xFF )) & ~0xC000;
|
||||
}
|
||||
|
||||
/*
|
||||
* getRawRotation
|
||||
*
|
||||
* Read Raw Angle Register Value
|
||||
*/
|
||||
uint16_t as5048a_getRawRotation(struct SPI_AS5048 *Sn)
|
||||
{
|
||||
volatile uint16_t rawAngle = as5048a_read(Sn, AS5048A_ANGLE);
|
||||
return rawAngle;
|
||||
}
|
||||
|
||||
int16_t as5048a_getRotation(struct SPI_AS5048 *Sn)
|
||||
{
|
||||
uint16_t data;
|
||||
int16_t rotation;
|
||||
|
||||
data = as5048a_getRawRotation(Sn);
|
||||
rotation = (int16_t)(data); //- static_cast<int16_t>(this->position);
|
||||
if (rotation > AS5048A_MAX_VALUE) {
|
||||
rotation = -((0x3FFF) - rotation); //more than -180
|
||||
}
|
||||
|
||||
return rotation;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* getRotationInDegrees
|
||||
*
|
||||
* Read angle register and return angle in Degrees
|
||||
*/
|
||||
float as5048a_getRotationInDegrees(struct SPI_AS5048 *Sn)
|
||||
{
|
||||
uint16_t rawAngle = as5048a_getRotation(Sn);
|
||||
float angleDegrees = 360.0 * (rawAngle + AS5048A_MAX_VALUE) / (AS5048A_MAX_VALUE * 2.0);;
|
||||
|
||||
return angleDegrees;
|
||||
}
|
||||
|
||||
|
||||
uint16_t as5048a_transfer16(struct SPI_AS5048 *Sn, uint16_t value)
|
||||
{
|
||||
uint8_t in_buf[2], out_buf[2];
|
||||
uint16_t wordRead;
|
||||
|
||||
out_buf[1] = value & 0xFF;
|
||||
out_buf[0] = ( value >> 8 ) & 0xFF;
|
||||
struct spi_xfer xfer;
|
||||
xfer.rxbuf = in_buf;
|
||||
xfer.txbuf = (uint8_t *)out_buf;
|
||||
xfer.size = 2;
|
||||
spi_m_sync_transfer(Sn->SPI_descr, &xfer);
|
||||
wordRead = (uint16_t)((in_buf[0] << 8) | in_buf[1]);
|
||||
return wordRead;
|
||||
}
|
||||
|
||||
uint8_t as5048a_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;
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* AS5048.h
|
||||
*
|
||||
* Created: 27/07/2021 16:12:53
|
||||
* Author: Nick-XMG
|
||||
*/
|
||||
|
||||
#ifndef AS5048_H_
|
||||
#define AS5048_H_
|
||||
#include <atmel_start.h>
|
||||
|
||||
|
||||
struct SPI_AS5048 {
|
||||
struct spi_m_sync_descriptor *SPI_descr;
|
||||
struct io_descriptor *io_descr;
|
||||
uint8_t state;
|
||||
uint8_t flags;
|
||||
uint32_t SS_pin;
|
||||
uint8_t *tx_buffer;
|
||||
uint8_t *rx_buffer;
|
||||
};
|
||||
|
||||
struct SPI_AS5048 AS_1;
|
||||
|
||||
void as5048a_init(struct spi_m_sync_descriptor *spi, struct SPI_AS5048 *Sn);
|
||||
void as5048a_State_Machine(struct SPI_AS5048 *Sn);
|
||||
//
|
||||
///* Sensor Specific Read Functions */
|
||||
uint16_t as5048a_read(struct SPI_AS5048 *Sn, uint16_t address);
|
||||
uint16_t as5048a_getRawRotation(struct SPI_AS5048 *Sn);
|
||||
int16_t as5048a_getRotation(struct SPI_AS5048 *Sn);
|
||||
float as5048a_getRotationInDegrees(struct SPI_AS5048 *Sn);
|
||||
//
|
||||
///* Support Functions */
|
||||
uint16_t as5048a_transfer16(struct SPI_AS5048 *Sn, uint16_t value);
|
||||
uint8_t as5048a_CalcEvenParity(uint16_t value);
|
||||
|
||||
#endif /* AS5048_H_ */
|
||||
@@ -442,6 +442,12 @@
|
||||
<Compile Include="A1335.h">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AS5048.c">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AS5048.h">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="atmel_start.c">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <atmel_start.h>
|
||||
#include "spi_slave_dma_config.h"
|
||||
#include "A1335.h"
|
||||
#include "AS5048.h"
|
||||
|
||||
/* Buffer length to transfer/receive */
|
||||
#define BUFFER_LEN (6)
|
||||
@@ -25,7 +26,8 @@ static struct timer_task TIMER_0_task1;
|
||||
static void task1_cb(const struct timer_task *const timer_task)
|
||||
{
|
||||
volatile int i = 0;
|
||||
angleSensor_State_Machine(&A1);
|
||||
//a1335_State_Machine(&A1);
|
||||
as5048a_State_Machine(&AS_1);
|
||||
|
||||
}
|
||||
|
||||
@@ -89,7 +91,8 @@ int main(void)
|
||||
atmel_start_init();
|
||||
/* Initialize SPI master IO and Callback */
|
||||
//spi_master_init();
|
||||
angleSensor_init(&SPI_1, &A1);
|
||||
//a1335_init(&SPI_1, &A1);
|
||||
as5048a_init(&SPI_1, &AS_1);
|
||||
TIMER_0_init();
|
||||
|
||||
//spi_m_dma_enable(&SPI_0);
|
||||
|
||||
Reference in New Issue
Block a user