Got Master/Slave Comms working

This commit is contained in:
Nicolas Trimborn
2021-07-28 23:24:30 +02:00
parent 128dbfe5c3
commit 2f5a303a0a
682 changed files with 589964 additions and 230 deletions

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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;

View File

@@ -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_ */

View File

@@ -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>

View File

@@ -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);