got angle sensor reading
This commit is contained in:
		
							parent
							
								
									312768d2cf
								
							
						
					
					
						commit
						128dbfe5c3
					
				| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Subproject commit f781cec322d7cd2a3677e1c273174ea00bc047e6
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					.pio
 | 
				
			||||||
 | 
					.vscode/.browse.c_cpp.db*
 | 
				
			||||||
 | 
					.vscode/c_cpp_properties.json
 | 
				
			||||||
 | 
					.vscode/launch.json
 | 
				
			||||||
 | 
					.vscode/ipch
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // See http://go.microsoft.com/fwlink/?LinkId=827846
 | 
				
			||||||
 | 
					    // for the documentation about the extensions.json format
 | 
				
			||||||
 | 
					    "recommendations": [
 | 
				
			||||||
 | 
					        "platformio.platformio-ide"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,144 @@
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <SPI.h>
 | 
				
			||||||
 | 
					#include "A1335.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define kNOERROR 0
 | 
				
			||||||
 | 
					#define kPRIMARYREADERROR 1
 | 
				
			||||||
 | 
					#define kEXTENDEDREADTIMEOUTERROR 2
 | 
				
			||||||
 | 
					#define kPRIMARYWRITEERROR 3
 | 
				
			||||||
 | 
					#define kEXTENDEDWRITETIMEOUTERROR 4
 | 
				
			||||||
 | 
					#define kCRCERROR 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define kUNABLETOCHANGEPROCESSORSTATE 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const uint16_t ChipSelectPin = 5;
 | 
				
			||||||
 | 
					const uint16_t LEDPin = 13;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					void setup() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint16_t unused;
 | 
				
			||||||
 | 
					   uint32_t flags;
 | 
				
			||||||
 | 
					  uint16_t angle;
 | 
				
			||||||
 | 
					  uint32_t flagsAndZeroOffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SPI.begin();
 | 
				
			||||||
 | 
					  // put your setup code here, to run once:
 | 
				
			||||||
 | 
					  Serial.begin(19200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   while (!Serial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pinMode(SS, OUTPUT);
 | 
				
			||||||
 | 
					  digitalWrite(SS, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Make sure all of the SPI pins are
 | 
				
			||||||
 | 
					  // ready by doing a read
 | 
				
			||||||
 | 
					  //PrimaryRead(ChipSelectPin, 0x0, unused);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Unlock the device
 | 
				
			||||||
 | 
					  ExtendedWrite(ChipSelectPin, 0xFFFE, 0x27811F77);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Make sure the device is unlocked
 | 
				
			||||||
 | 
					  ExtendedRead(ChipSelectPin, 0x22, flags);
 | 
				
			||||||
 | 
					  if (!((flags & 0x0022) == 0x0020))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					      Serial.println("Device is not Unlocked");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Zero the angle
 | 
				
			||||||
 | 
					  // Extended location 0x06 contains flags in the MSW and the Zero Angle values in the LSW
 | 
				
			||||||
 | 
					  // so get both and zero out ZeroAngle
 | 
				
			||||||
 | 
					  ExtendedRead(ChipSelectPin, 0x06, flagsAndZeroOffset);
 | 
				
			||||||
 | 
					  flagsAndZeroOffset = (flagsAndZeroOffset & 0xFFFF0000);
 | 
				
			||||||
 | 
					  ExtendedWrite(ChipSelectPin, 0x06, flagsAndZeroOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Get the current angle. It is now without the ZeroAngle correction
 | 
				
			||||||
 | 
					  PrimaryRead(ChipSelectPin, 0x20, angle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Copy the read angle into location 0x5C preserving the flags
 | 
				
			||||||
 | 
					  flagsAndZeroOffset = (flagsAndZeroOffset & 0xFFFF0000) | ((angle << 4) & 0x0000FFFF);
 | 
				
			||||||
 | 
					  ExtendedWrite(ChipSelectPin, 0x06, flagsAndZeroOffset);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* uint16_t angle_read;
 | 
				
			||||||
 | 
					  Serial.println("Init Complete");
 | 
				
			||||||
 | 
					  PrimaryRead(ChipSelectPin, 0x20, angle_read);
 | 
				
			||||||
 | 
					  Serial.print("Angle= ");
 | 
				
			||||||
 | 
					  Serial.println(angle_read); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void loop() {
 | 
				
			||||||
 | 
					  uint16_t angle;
 | 
				
			||||||
 | 
					    uint16_t temperature;
 | 
				
			||||||
 | 
					    uint16_t fieldStrength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Every second, read the angle, temperature and field strength
 | 
				
			||||||
 | 
					    if (nextTime < millis())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (PrimaryRead(ChipSelectPin, 0x20, angle) == kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					            if (CalculateParity(angle))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Serial.print("Angle = ");
 | 
				
			||||||
 | 
					                Serial.print((float)(angle & 0x0FFF) * 360.0 / 4096.0);
 | 
				
			||||||
 | 
					                Serial.println(" Degrees");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Serial.println("Parity error on Angle read");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Serial.println("Unable to read Angle");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (PrimaryRead(ChipSelectPin, 0x28, temperature) == kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Serial.print("Temperature = ");
 | 
				
			||||||
 | 
					      Serial.print(((float)(temperature & 0x0FFF) / 8.0) - 273.15);
 | 
				
			||||||
 | 
					      Serial.println(" C");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Serial.println("Unable to read Temperature");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (PrimaryRead(ChipSelectPin, 0x2A, fieldStrength) == kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Serial.print("Field Strength = ");
 | 
				
			||||||
 | 
					      Serial.print(fieldStrength & 0x0FFF);
 | 
				
			||||||
 | 
					      Serial.println(" Gauss");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Serial.println("Unable to read Field Strength");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nextTime = millis() + 500L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Blink the LED every half second
 | 
				
			||||||
 | 
					        if (ledOn)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            digitalWrite(LEDPin, LOW);
 | 
				
			||||||
 | 
					            ledOn = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            digitalWrite(LEDPin, HIGH);
 | 
				
			||||||
 | 
					            ledOn = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,39 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This directory is intended for project header files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A header file is a file containing C declarations and macro definitions
 | 
				
			||||||
 | 
					to be shared between several project source files. You request the use of a
 | 
				
			||||||
 | 
					header file in your project source file (C, C++, etc) located in `src` folder
 | 
				
			||||||
 | 
					by including it, with the C preprocessing directive `#include'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```src/main.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "header.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main (void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Including a header file produces the same results as copying the header file
 | 
				
			||||||
 | 
					into each source file that needs it. Such copying would be time-consuming
 | 
				
			||||||
 | 
					and error-prone. With a header file, the related declarations appear
 | 
				
			||||||
 | 
					in only one place. If they need to be changed, they can be changed in one
 | 
				
			||||||
 | 
					place, and programs that include the header file will automatically use the
 | 
				
			||||||
 | 
					new version when next recompiled. The header file eliminates the labor of
 | 
				
			||||||
 | 
					finding and changing all the copies as well as the risk that a failure to
 | 
				
			||||||
 | 
					find one copy will result in inconsistencies within a program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In C, the usual convention is to give header files names that end with `.h'.
 | 
				
			||||||
 | 
					It is most portable to use only letters, digits, dashes, and underscores in
 | 
				
			||||||
 | 
					header file names, and at most one dot.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Read more about using header files in official GCC documentation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Include Syntax
 | 
				
			||||||
 | 
					* Include Operation
 | 
				
			||||||
 | 
					* Once-Only Headers
 | 
				
			||||||
 | 
					* Computed Includes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,342 @@
 | 
				
			||||||
 | 
					/***************************************************
 | 
				
			||||||
 | 
					  Arduino library for the Allegro A1335 Magnetic angle sensor
 | 
				
			||||||
 | 
					  The A1335 sensor detects the absolute angular position of a 
 | 
				
			||||||
 | 
					  permanent magnet, typically a diametrically
 | 
				
			||||||
 | 
					  magnetized cylinder on the rotating shaft.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * by Florian von Bertrab
 | 
				
			||||||
 | 
					 ****************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "A1335.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bytes_2::bytes_2(){
 | 
				
			||||||
 | 
					  data.integer = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bytes_2::bytes_2(int16_t integ){
 | 
				
			||||||
 | 
					  data.integer = integ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int16_t&   bytes_2::in(){
 | 
				
			||||||
 | 
					  return data.integer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte&      bytes_2::lsBy(byte n){
 | 
				
			||||||
 | 
					  if (n > 1) {
 | 
				
			||||||
 | 
					    n = 1;
 | 
				
			||||||
 | 
					  } else if (n < 0) {
 | 
				
			||||||
 | 
					    n = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.bytes[n];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte&      bytes_2::msBy(byte n){
 | 
				
			||||||
 | 
					  if (n > 1) {
 | 
				
			||||||
 | 
					    n = 1;
 | 
				
			||||||
 | 
					  } else if (n < 0) {
 | 
				
			||||||
 | 
					    n = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.bytes[1-n];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bytes_4::bytes_4(){
 | 
				
			||||||
 | 
					  data.integer = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bytes_4::bytes_4(int32_t integ){
 | 
				
			||||||
 | 
					  data.integer = integ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int32_t&   bytes_4::in(){
 | 
				
			||||||
 | 
					  return data.integer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte&      bytes_4::lsBy(byte n){
 | 
				
			||||||
 | 
					  if (n > 3) {
 | 
				
			||||||
 | 
					    n = 3;
 | 
				
			||||||
 | 
					  } else if (n < 0) {
 | 
				
			||||||
 | 
					    n = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.bytes[n];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte&      bytes_4::msBy(byte n){
 | 
				
			||||||
 | 
					  if (n > 3) {
 | 
				
			||||||
 | 
					    n = 3;
 | 
				
			||||||
 | 
					  } else if (n < 0) {
 | 
				
			||||||
 | 
					    n = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.bytes[3-n];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//--- Normal Write Registers ---//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const byte EWA    = 0x02;   // Extended Write Address
 | 
				
			||||||
 | 
					const byte EWD    = 0x04;   // Extended Write Data
 | 
				
			||||||
 | 
					const byte EWCS   = 0x08;   // Extended Write Control and Status
 | 
				
			||||||
 | 
					const byte ERA    = 0x0A;   // Extended Read Address
 | 
				
			||||||
 | 
					const byte ERCS   = 0x0C;   // Extended Read Control and Status
 | 
				
			||||||
 | 
					const byte ERD    = 0x0E;   // Extended Read Data
 | 
				
			||||||
 | 
					const byte CTRL   = 0x1E;   // Device control
 | 
				
			||||||
 | 
					const byte ANG    = 0x20;   // Current angle and related data
 | 
				
			||||||
 | 
					const byte STA    = 0x22;   // Device status
 | 
				
			||||||
 | 
					const byte ERR    = 0x24;   // Device error status
 | 
				
			||||||
 | 
					const byte XERR   = 0x26;   // Extended error status
 | 
				
			||||||
 | 
					const byte TSEN   = 0x28;   // Temperature sensor data
 | 
				
			||||||
 | 
					const byte FIELD  = 0x2A;   // Magnetic field strength
 | 
				
			||||||
 | 
					const byte ERM    = 0x34;   // Device error status masking
 | 
				
			||||||
 | 
					const byte XERM   = 0x36;   // Extended error status masking
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//--- Extended Write Registers ---//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const int16_t ORATE = 0xFFD0;  // Output Rate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Control bytes and their respective keycodes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//                      CTRL(0x1E) KEY(0x1F)
 | 
				
			||||||
 | 
					//  Processor State
 | 
				
			||||||
 | 
					const byte ipm[]    = { B10000000, 0x46     }; // Idle mode
 | 
				
			||||||
 | 
					const byte rpm[]    = { B11000000, 0x46     }; // Run  mode
 | 
				
			||||||
 | 
					//  Hard Reset
 | 
				
			||||||
 | 
					const byte hre[]    = { B00100000, 0xB9     }; // Hard reset
 | 
				
			||||||
 | 
					//  Soft Reset
 | 
				
			||||||
 | 
					const byte sre[]    = { B00010000, 0xB9     }; // Soft reset
 | 
				
			||||||
 | 
					//  Clear STA
 | 
				
			||||||
 | 
					const byte csta[]   = { B00000100, 0x46     }; // Clear (STA)  registers
 | 
				
			||||||
 | 
					//  Hard Reset
 | 
				
			||||||
 | 
					const byte cxerr[]  = { B00000010, 0x46     }; // Clear (XERR) registers
 | 
				
			||||||
 | 
					//  Hard Reset
 | 
				
			||||||
 | 
					const byte cerr[]   = { B00000001, 0x46     }; // Clear (ERR)  registers
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Angle Register read masks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//                      ANG(0x20)  ANG+1(0x21)
 | 
				
			||||||
 | 
					// Register Identifier Code
 | 
				
			||||||
 | 
					const byte ria[]    = { B10000000, B00000000}; // Always 0
 | 
				
			||||||
 | 
					// Error Flag
 | 
				
			||||||
 | 
					const byte efa[]    = { B01000000, B00000000}; // At least one error in register 0x24
 | 
				
			||||||
 | 
					// New Flag
 | 
				
			||||||
 | 
					const byte nfa[]    = { B00100000, B00000000}; // A new angle is in the angle register
 | 
				
			||||||
 | 
					// Parity
 | 
				
			||||||
 | 
					const byte par[]    = { B00010000, B00000000}; // Odd parity bit for the whole register
 | 
				
			||||||
 | 
					// Angle
 | 
				
			||||||
 | 
					const byte ang[]    = { B00001111, B11111111}; // Encoded angle reading (n * 360/4096 = angle in deg.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Status Register read masks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//                      STA(0x20)  STA+1(0x21)
 | 
				
			||||||
 | 
					// Register Identifier Code
 | 
				
			||||||
 | 
					const byte ris[]    = { B11110000, B00000000}; // Always 1000
 | 
				
			||||||
 | 
					// Power-On Reset Flag
 | 
				
			||||||
 | 
					const byte por[]    = { B00001000, B00000000}; // There was a power-on reset since last field reset
 | 
				
			||||||
 | 
					// Soft Reset Flag
 | 
				
			||||||
 | 
					const byte srf[]    = { B00000100, B00000000}; // There was a soft reset since last field reset
 | 
				
			||||||
 | 
					// New Flag
 | 
				
			||||||
 | 
					const byte nfs[]    = { B00000010, B00000000}; // A new angle is in the angle register
 | 
				
			||||||
 | 
					// Current Error Flag
 | 
				
			||||||
 | 
					const byte efs[]    = { B00000001, B00000000}; // At least one error in register 0x24
 | 
				
			||||||
 | 
					// Processor Processing Status
 | 
				
			||||||
 | 
					const byte mps[]    = { B00000000, B11110000}; // 0000 Booting; 0001 Idle or Processing angles; 1110 Self-testmode
 | 
				
			||||||
 | 
					// Processor Phase Status
 | 
				
			||||||
 | 
					const byte phase[]  = { B00000000, B00001111}; // 0000 Idle; 0001 Processing angles; Only in Self-test mode [0100 Built in self test; 0110 ROM checksum; 0111 CVH self test]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Temperature Register read masks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//                      TSEN(0x28) TSEN+1(0x29)
 | 
				
			||||||
 | 
					// Register Identifier Code
 | 
				
			||||||
 | 
					const byte rit[]    = { B11110000, B00000000}; // Always 1111
 | 
				
			||||||
 | 
					// Temperature
 | 
				
			||||||
 | 
					const byte temp[]   = { B00001111, B11111111}; // Encoded temperature reading (n / 8 = temperature in K)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Field Strenght Register read masks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//                      FIELD(0x28) FIELD+1(0x29)
 | 
				
			||||||
 | 
					// Register Identifier Code
 | 
				
			||||||
 | 
					const byte rif[]    = { B11110000, B00000000}; // Always 1110
 | 
				
			||||||
 | 
					// Magnetic field strenght
 | 
				
			||||||
 | 
					const byte field[]  = { B00001111, B11111111}; // Magnetic field strenght reading (n = field strenght in Gauss (1/10000 T))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A1335::A1335(){
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int16_t   A1335::getAddress(){                  // returns I2C address of the sensor
 | 
				
			||||||
 | 
					  return address;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::getProcessorState(){           // returns current processor state of the sensor
 | 
				
			||||||
 | 
					  return processorState;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::getOutputRate(){               // returns the current sample rate of the sensor
 | 
				
			||||||
 | 
					  return outputRate;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::start(int16_t address_){        // Initializes the sensor at the address given and fills the private variables
 | 
				
			||||||
 | 
					  Wire.beginTransmission(address);
 | 
				
			||||||
 | 
					  byte error = Wire.endTransmission();
 | 
				
			||||||
 | 
					  if (error) {
 | 
				
			||||||
 | 
					    processorState = 4;
 | 
				
			||||||
 | 
					    return error;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  address = address_;
 | 
				
			||||||
 | 
					  bytes_2 state(normalRead(STA));
 | 
				
			||||||
 | 
					  bytes_4 orate(extendedRead(ORATE));
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  byte processing_status = (state.msBy(1) & mps[1]) >> 4;
 | 
				
			||||||
 | 
					  byte processing_phase =  (state.msBy(1) & phase[1]) >> 0;
 | 
				
			||||||
 | 
					  switch (processing_status) {
 | 
				
			||||||
 | 
					    case B00000000:
 | 
				
			||||||
 | 
					      processorState = 0;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case B00000001:
 | 
				
			||||||
 | 
					      if (processing_phase == 0){
 | 
				
			||||||
 | 
					        processorState = 1;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        processorState = 2;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case B00001110:
 | 
				
			||||||
 | 
					      processorState = 3;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  outputRate = orate.msBy(3);
 | 
				
			||||||
 | 
					  delay(1);
 | 
				
			||||||
 | 
					  return error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double    A1335::readAngle(){       // returns Angle in Degrees
 | 
				
			||||||
 | 
					  return double(readAngleRaw()) * 360.0 / 4096.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					uint16_t  A1335::readAngleRaw(){    // returns raw angle data
 | 
				
			||||||
 | 
					  bytes_2 angReg(normalRead(ANG));
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  int16_t parityCheck = angReg.in();
 | 
				
			||||||
 | 
					  parityCheck ^= parityCheck >> 8;
 | 
				
			||||||
 | 
					  parityCheck ^= parityCheck >> 4;
 | 
				
			||||||
 | 
					  parityCheck ^= parityCheck >> 2;
 | 
				
			||||||
 | 
					  parityCheck ^= parityCheck >> 1;
 | 
				
			||||||
 | 
					  parityCheck &= 1;                 // parity Check now contains the parity of all bits in angReg
 | 
				
			||||||
 | 
					  if(!parityCheck) {                // odd Parity in this register => a 0 means an error
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  angReg.msBy(0) &= ang[0];           // mutes bits, that dont contain the angle data
 | 
				
			||||||
 | 
					  return angReg.in();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double    A1335::readTemp(){        // returns temperature in Kelvin
 | 
				
			||||||
 | 
					  return double(readTempRaw())/8.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t  A1335::readTempRaw(){     // returns raw temperature data
 | 
				
			||||||
 | 
					  bytes_2 tempReg(normalRead(TSEN));
 | 
				
			||||||
 | 
					  tempReg.msBy(0) &= temp[0];         // mutes bits, that dont contain temperature data
 | 
				
			||||||
 | 
					  return tempReg.in();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double    A1335::readField(){       // returns field strenght in Tesla
 | 
				
			||||||
 | 
					  return double(readFieldRaw())/10000.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t  A1335::readFieldRaw(){    // returns raw field strenght data
 | 
				
			||||||
 | 
					  bytes_2 fieldReg(normalRead(FIELD));
 | 
				
			||||||
 | 
					  fieldReg.msBy(0) &= field[0];       // mutes bits, that dont contain temperature data
 | 
				
			||||||
 | 
					  return fieldReg.in();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::readOutputRate(){  // reads the log2() of the sample rate 
 | 
				
			||||||
 | 
					  bytes_4 oRate(extendedRead(ORATE));
 | 
				
			||||||
 | 
					  return oRate.msBy(3);             // !!!  I don't know yet, which byte holds the output rate  !!!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::setOutputRate(byte rate){  // sets the log2() of the sample rate => (ORate = 2^rate)
 | 
				
			||||||
 | 
					  if (rate < 0) {
 | 
				
			||||||
 | 
					    rate = 0;
 | 
				
			||||||
 | 
					  } else if (rate >=8) {
 | 
				
			||||||
 | 
					    rate = 7;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  bytes_2 idle_mode;
 | 
				
			||||||
 | 
					  bytes_2 run_mode;
 | 
				
			||||||
 | 
					  for (int i = 0; i < 2; i++){
 | 
				
			||||||
 | 
					    idle_mode.msBy(i) = ipm[i];
 | 
				
			||||||
 | 
					    run_mode.msBy(i)  = rpm[i];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  normalWrite(CTRL, idle_mode.in());
 | 
				
			||||||
 | 
					  delayMicroseconds(150);
 | 
				
			||||||
 | 
					  bytes_4 oRate;
 | 
				
			||||||
 | 
					  oRate.msBy(3) = rate;
 | 
				
			||||||
 | 
					  extendedWrite(ORATE, oRate.in());       // !!!  I don't know yet, which byte gets the output rate  !!!
 | 
				
			||||||
 | 
					  delayMicroseconds(50);
 | 
				
			||||||
 | 
					  normalWrite(CTRL, run_mode.in());
 | 
				
			||||||
 | 
					  delayMicroseconds(150);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::normalWrite(byte reg, int16_t data){      // writes the 2 bytes in "bytes" to the register with address reg to the sensor with I2C address adress.
 | 
				
			||||||
 | 
					  bytes_2 data_bytes(data);
 | 
				
			||||||
 | 
					  Wire.beginTransmission(address);
 | 
				
			||||||
 | 
					  Wire.write(reg);                                        // choose target register
 | 
				
			||||||
 | 
					  for (int i = 0; i<2; i++){
 | 
				
			||||||
 | 
					    Wire.write(data_bytes.msBy(i));                       // Writes data MSB first
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return Wire.endTransmission();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte      A1335::extendedWrite(int16_t reg, int32_t data){ // writes the 4 bytes in "bytes" to the extended register with address reg to the sensor with I2C address adress.
 | 
				
			||||||
 | 
					  bytes_4 data_bytes(data);
 | 
				
			||||||
 | 
					  Wire.beginTransmission(address);
 | 
				
			||||||
 | 
					  Wire.write(EWA);                                        // choose write Register
 | 
				
			||||||
 | 
					  Wire.write(byte(reg >> 8));                             // Fill with target address
 | 
				
			||||||
 | 
					  Wire.write(byte(reg));
 | 
				
			||||||
 | 
					  for (int i = 0; i<4; i++){
 | 
				
			||||||
 | 
					    Wire.write(data_bytes.msBy(i));                       // Writes data MSB first
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  Wire.write(0x80);                                       // Confirm write
 | 
				
			||||||
 | 
					  Wire.endTransmission();
 | 
				
			||||||
 | 
					  delayMicroseconds(10);
 | 
				
			||||||
 | 
					  Wire.requestFrom(address, 1);
 | 
				
			||||||
 | 
					  return Wire.read();                                     // Returns 1 if it works
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int16_t   A1335::normalRead(byte reg){
 | 
				
			||||||
 | 
					  bytes_2 data;
 | 
				
			||||||
 | 
					  Wire.beginTransmission(address);
 | 
				
			||||||
 | 
					  Wire.write(reg);                // choose target Register
 | 
				
			||||||
 | 
					  Wire.endTransmission();
 | 
				
			||||||
 | 
					  Wire.requestFrom(address, 2);
 | 
				
			||||||
 | 
					  for(int i=0; i< 2; i++){
 | 
				
			||||||
 | 
					    if (Wire.available()){
 | 
				
			||||||
 | 
					      data.msBy(i) = Wire.read();   // read data bytes
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.in();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int32_t   A1335::extendedRead(int16_t reg){
 | 
				
			||||||
 | 
					  bytes_4 data;
 | 
				
			||||||
 | 
					  byte rstate;
 | 
				
			||||||
 | 
					  Wire.beginTransmission(address);
 | 
				
			||||||
 | 
					  Wire.write(ERA);                // choose write Register
 | 
				
			||||||
 | 
					  Wire.write(byte(reg >> 8));     // Fill with target address
 | 
				
			||||||
 | 
					  Wire.write(byte(reg));
 | 
				
			||||||
 | 
					  Wire.write(0x80);               // Confirm read
 | 
				
			||||||
 | 
					  Wire.endTransmission();
 | 
				
			||||||
 | 
					  delayMicroseconds(10);
 | 
				
			||||||
 | 
					  Wire.requestFrom(address,5);
 | 
				
			||||||
 | 
					  rstate = Wire.read();           // Reads status byte
 | 
				
			||||||
 | 
					  for(int i=0; i < 4; i++){
 | 
				
			||||||
 | 
					    if (Wire.available()){
 | 
				
			||||||
 | 
					      data.msBy(i) = Wire.read();    // Reads data bytes
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return data.in();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,99 @@
 | 
				
			||||||
 | 
					/***************************************************
 | 
				
			||||||
 | 
					  Arduino library for the Allegro A1335 Magnetic angle sensor
 | 
				
			||||||
 | 
					  The A1335 sensor detects the absolute angular position of a 
 | 
				
			||||||
 | 
					  permanent magnet, typically a diametrically
 | 
				
			||||||
 | 
					  magnetized cylinder on the rotating shaft.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * by Florian von Bertrab
 | 
				
			||||||
 | 
					 ****************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef A1335_H
 | 
				
			||||||
 | 
					#define A1335_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if (ARDUINO >= 100)
 | 
				
			||||||
 | 
					     #include "Arduino.h"
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					     #include "WProgram.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include <Wire.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class bytes_2 { // allows easy conversion from two bytes in a given order to a 16 bit int.
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  bytes_2();
 | 
				
			||||||
 | 
					  bytes_2(int16_t integ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int16_t&   in();
 | 
				
			||||||
 | 
					  byte&      lsBy(byte n);
 | 
				
			||||||
 | 
					  byte&      msBy(byte n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  union     {
 | 
				
			||||||
 | 
					    int16_t integer;
 | 
				
			||||||
 | 
					    byte    bytes[2];
 | 
				
			||||||
 | 
					  }data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class bytes_4 { // allows easy conversion from four bytes in a given order to a 32 bit int.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  bytes_4();
 | 
				
			||||||
 | 
					  bytes_4(int32_t integ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t&   in();
 | 
				
			||||||
 | 
					  byte&      lsBy(byte n);
 | 
				
			||||||
 | 
					  byte&      msBy(byte n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  union     {
 | 
				
			||||||
 | 
					    int32_t integer;
 | 
				
			||||||
 | 
					    byte    bytes[4];
 | 
				
			||||||
 | 
					  }data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class A1335 {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  A1335();  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte      start(int16_t address_);	// starts the sensor at the given address
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  int16_t   getAddress();			// returns I2C address
 | 
				
			||||||
 | 
					  byte      getProcessorState();		// returns processor state:
 | 
				
			||||||
 | 
												// 0 = booting; 1 = idle; 2 = running; 3 = self-test mode; 4 = not found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte      getOutputRate();		// returns the log2() of the samperate. E.g. 3 would mean 8 samples per data point.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  double    readAngle();			// returns the angle in degrees
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint16_t  readAngleRaw();			// returns raw angle data (4096 = 360°)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double    readTemp();			// returns temperature in Kelvin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint16_t  readTempRaw();			// returns raw temperature data 8 = 1 K
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double    readField();			// returns field strenght in Tesla
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint16_t  readFieldRaw();			// returns raw field strenght data 10 = 1mT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte      readOutputRate();		// reads the log2() of the sample rate. Does not really work yet!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte      setOutputRate(byte rate);// sets the log2() of the sample rate => (ORate = 2^rate). Does not really work yet!
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  byte      normalWrite(byte reg, int16_t data); // writes 16 bit to a given register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int16_t   normalRead(byte reg);			 // reads 16 bit from a given register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  byte      extendedWrite(int16_t reg, int32_t data); // writes 32 bit to a given extended register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t   extendedRead(int16_t reg);			 // reads 32 bit from a given extended register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int16_t   address = 0x0C;             // I2C address
 | 
				
			||||||
 | 
					  byte      processorState = 4;         // 0 = booting; 1 = idle; 2 = running; 3 = self-test mode; 4 = not found
 | 
				
			||||||
 | 
					  byte      outputRate = 0;                 // log2() of the sample rate in the EEPROM
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //A1335_H
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					# Allegro-A1335-Sensor-library
 | 
				
			||||||
 | 
					A C++ library for communicating with the A 1335 hall effect encoder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Arduino library for the Allegro A1335 Magnetic angle sensor.
 | 
				
			||||||
 | 
					The A1335 sensor detects the absolute angular position of a permanent magnet, typically a diametrically magnetized cylinder on the rotating shaft.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* by Florian von Bertrab
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Subproject commit f781cec322d7cd2a3677e1c273174ea00bc047e6
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This directory is intended for project specific (private) libraries.
 | 
				
			||||||
 | 
					PlatformIO will compile them to static libraries and link into executable file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The source code of each library should be placed in a an own separate directory
 | 
				
			||||||
 | 
					("lib/your_library_name/[here are source files]").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example, see a structure of the following two libraries `Foo` and `Bar`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|--lib
 | 
				
			||||||
 | 
					|  |
 | 
				
			||||||
 | 
					|  |--Bar
 | 
				
			||||||
 | 
					|  |  |--docs
 | 
				
			||||||
 | 
					|  |  |--examples
 | 
				
			||||||
 | 
					|  |  |--src
 | 
				
			||||||
 | 
					|  |     |- Bar.c
 | 
				
			||||||
 | 
					|  |     |- Bar.h
 | 
				
			||||||
 | 
					|  |  |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
 | 
				
			||||||
 | 
					|  |
 | 
				
			||||||
 | 
					|  |--Foo
 | 
				
			||||||
 | 
					|  |  |- Foo.c
 | 
				
			||||||
 | 
					|  |  |- Foo.h
 | 
				
			||||||
 | 
					|  |
 | 
				
			||||||
 | 
					|  |- README --> THIS FILE
 | 
				
			||||||
 | 
					|
 | 
				
			||||||
 | 
					|- platformio.ini
 | 
				
			||||||
 | 
					|--src
 | 
				
			||||||
 | 
					   |- main.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and a contents of `src/main.c`:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					#include <Foo.h>
 | 
				
			||||||
 | 
					#include <Bar.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main (void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PlatformIO Library Dependency Finder will find automatically dependent
 | 
				
			||||||
 | 
					libraries scanning project source files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More information about PlatformIO Library Dependency Finder
 | 
				
			||||||
 | 
					- https://docs.platformio.org/page/librarymanager/ldf.html
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					; PlatformIO Project Configuration File
 | 
				
			||||||
 | 
					;
 | 
				
			||||||
 | 
					;   Build options: build flags, source filter
 | 
				
			||||||
 | 
					;   Upload options: custom upload port, speed and extra flags
 | 
				
			||||||
 | 
					;   Library options: dependencies, extra library storages
 | 
				
			||||||
 | 
					;   Advanced options: extra scripting
 | 
				
			||||||
 | 
					;
 | 
				
			||||||
 | 
					; Please visit documentation for the other options and examples
 | 
				
			||||||
 | 
					; https://docs.platformio.org/page/projectconf.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[env:esp32doit-devkit-v1]
 | 
				
			||||||
 | 
					platform = espressif32
 | 
				
			||||||
 | 
					board = esp32doit-devkit-v1
 | 
				
			||||||
 | 
					framework = arduino
 | 
				
			||||||
 | 
					upload_speed = 115200
 | 
				
			||||||
 | 
					uploade_port = COM7
 | 
				
			||||||
 | 
					upload_protocol = esptool
 | 
				
			||||||
 | 
					monitor_speed = 19200
 | 
				
			||||||
 | 
					lib_deps = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[env:SAMC21]
 | 
				
			||||||
 | 
					platform = atmelsam
 | 
				
			||||||
 | 
					framework = arduino
 | 
				
			||||||
 | 
					board = samc21_xpro
 | 
				
			||||||
 | 
					upload_protocol = cmsis-dap
 | 
				
			||||||
 | 
					upload_port = COM3
 | 
				
			||||||
 | 
					lib_deps = https://github.com/hugllc/samc21_can.git
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,569 @@
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <SPI.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define kNOERROR 0
 | 
				
			||||||
 | 
					#define kPRIMARYREADERROR 1
 | 
				
			||||||
 | 
					#define kEXTENDEDREADTIMEOUTERROR 2
 | 
				
			||||||
 | 
					#define kPRIMARYWRITEERROR 3
 | 
				
			||||||
 | 
					#define kEXTENDEDWRITETIMEOUTERROR 4
 | 
				
			||||||
 | 
					#define kCRCERROR 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define kUNABLETOCHANGEPROCESSORSTATE 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const uint16_t ChipSelectPin = 5;
 | 
				
			||||||
 | 
					const uint16_t LEDPin = 13;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * CalculateParity
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * From the 16 bit input, calculate the parity
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool CalculateParity(uint16_t input)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t count = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Count up the number of 1s in the input
 | 
				
			||||||
 | 
					    for (int index = 0; index < 16; ++index)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ((input & 1) == 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ++count;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        input >>= 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // return true if there is an odd number of 1s
 | 
				
			||||||
 | 
					    return (count & 1) != 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * CalculateCRC
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Take the 16bit input and generate a 4bit CRC
 | 
				
			||||||
 | 
					 * Polynomial = x^4 + x^1 + 1
 | 
				
			||||||
 | 
					 * LFSR preset to all 1's
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint8_t CalculateCRC(uint16_t input)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool CRC0 = true;
 | 
				
			||||||
 | 
					    bool CRC1 = true;
 | 
				
			||||||
 | 
					    bool CRC2 = true;
 | 
				
			||||||
 | 
					    bool CRC3 = true;
 | 
				
			||||||
 | 
					    int  i;
 | 
				
			||||||
 | 
					    bool DoInvert;
 | 
				
			||||||
 | 
					    uint16_t mask = 0x8000;
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					    for (i = 0; i < 16; ++i)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DoInvert = ((input & mask) != 0) ^ CRC3;         // XOR required?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CRC3 = CRC2;
 | 
				
			||||||
 | 
					        CRC2 = CRC1;
 | 
				
			||||||
 | 
					        CRC1 = CRC0 ^ DoInvert;
 | 
				
			||||||
 | 
					        CRC0 = DoInvert;
 | 
				
			||||||
 | 
					        mask >>= 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (CRC3 ? 8U : 0U) + (CRC2 ? 4U : 0U) + (CRC1 ? 2U : 0U) + (CRC0 ? 1U : 0U);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * PrimaryRead
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Read from the primary serial registers
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint16_t PrimaryRead(uint16_t cs, uint16_t address, uint16_t& value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (includeCRC)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint8_t crcValue;
 | 
				
			||||||
 | 
					        uint8_t crcCommand;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // On the Teensy, SPI0_CTAR0 is used to describe the SPI transaction for transfer (byte)
 | 
				
			||||||
 | 
					        // while SPI0_CTAR1 is used to describe the SPI transaction for transfer16.
 | 
				
			||||||
 | 
					        // To do a 20 bit transfer, change the length of the transaction to 4 bits for transfer
 | 
				
			||||||
 | 
					        // and do a transfer16 followed by a transfer.
 | 
				
			||||||
 | 
					        //uint32_t oldSPI0_CTAR0 = SPI0_CTAR0;
 | 
				
			||||||
 | 
					       // SPI0_CTAR0 = (SPI0_CTAR0 & 0x87FFFFFF) | SPI_CTAR_FMSZ(3);    //  using SPI0_CTAR0 to send 4 bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Combine the register address and the command into one byte
 | 
				
			||||||
 | 
					        uint16_t command = ((address & ADDRESS_MASK) | READ) << 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        crcCommand = CalculateCRC(command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select low to select the device
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // send the device the register you want to read
 | 
				
			||||||
 | 
					        SPI.transfer16(command);
 | 
				
			||||||
 | 
					        SPI.transfer(crcCommand);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // send the command again to read the contents
 | 
				
			||||||
 | 
					        value = SPI.transfer16(command);
 | 
				
			||||||
 | 
					        crcValue = SPI.transfer(crcCommand);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select high to de-select
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Restore the 8 bit description
 | 
				
			||||||
 | 
					        //SPI0_CTAR0 = oldSPI0_CTAR0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check the CRC value
 | 
				
			||||||
 | 
					        if (CalculateCRC(value) != crcValue)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return kCRCERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Combine the register address and the command into one byte
 | 
				
			||||||
 | 
					        uint16_t command = ((address & ADDRESS_MASK) | READ) << 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select low to select the device
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // send the device the register you want to read
 | 
				
			||||||
 | 
					        SPI.transfer16(command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // send the command again to read the contents
 | 
				
			||||||
 | 
					        value = SPI.transfer16(command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select high to de-select
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.endTransaction();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return kNOERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * PrimaryWrite
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Write to the primary serial registers
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint16_t PrimaryWrite(uint16_t cs, uint16_t address, uint16_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (includeCRC)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // On the Teensy, SPI0_CTAR0 is used to describe the SPI transaction for transfer
 | 
				
			||||||
 | 
					        // while SPI0_CTAR1 is used to describe the SPI transaction for transfer16.
 | 
				
			||||||
 | 
					        // To do a 20 bit transfer, change the length of the transaction to 4 bits for transfer
 | 
				
			||||||
 | 
					        // and do a transfer16 followed by a transfer.
 | 
				
			||||||
 | 
					        //uint32_t oldSPI0_CTAR0 = SPI0_CTAR0;
 | 
				
			||||||
 | 
					       // SPI0_CTAR0 = (SPI0_CTAR0 & 0x87FFFFFF) | SPI_CTAR_FMSZ(3);    //  using SPI0_CTAR0 to send 4 bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Combine the register address and the command into one byte
 | 
				
			||||||
 | 
					        uint16_t command = (((address & ADDRESS_MASK) | WRITE) << 8)  | ((value >> 8) & 0x0FF);
 | 
				
			||||||
 | 
					        uint8_t crcCommand = CalculateCRC(command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select low to select the device:
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.transfer16(command); // Send most significant byte of register data
 | 
				
			||||||
 | 
					        SPI.transfer(crcCommand); // Send the crc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select high to de-select:
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        command = ((((address + 1) & ADDRESS_MASK) | WRITE) << 8 ) | (value & 0x0FF);
 | 
				
			||||||
 | 
					        crcCommand = CalculateCRC(command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select low to select the device:
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.transfer16(command); // Send least significant byte of register data
 | 
				
			||||||
 | 
					        SPI.transfer(crcCommand); // Send the crc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select high to de-select:
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Restore the 8 bit description
 | 
				
			||||||
 | 
					        //SPI0_CTAR0 = oldSPI0_CTAR0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.endTransaction();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Combine the register address and the command into one byte
 | 
				
			||||||
 | 
					        uint16_t command = ((address & ADDRESS_MASK) | WRITE) << 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select low to select the device:
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.transfer16(command | ((value >> 8) & 0x0FF)); // Send most significant byte of register data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select high to de-select:
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        command = (((address + 1) & ADDRESS_MASK) | WRITE) << 8;
 | 
				
			||||||
 | 
					        // take the chip select low to select the device:
 | 
				
			||||||
 | 
					        digitalWrite(cs, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.transfer16(command | (value & 0x0FF)); // Send least significant byte of register data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // take the chip select high to de-select:
 | 
				
			||||||
 | 
					        digitalWrite(cs, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SPI.endTransaction();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return kNOERROR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ExtendedRead
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Read from the SRAM, EEPROM, AUX or Extended Registers
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint16_t ExtendedRead(uint16_t cs, uint16_t address, uint32_t& value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t results;
 | 
				
			||||||
 | 
					    uint16_t readFlags;
 | 
				
			||||||
 | 
					    uint32_t timeout;
 | 
				
			||||||
 | 
					    uint16_t valueMSW;
 | 
				
			||||||
 | 
					    uint16_t valueLSW;
 | 
				
			||||||
 | 
					    uint32_t currentTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Write the address to the Extended Read Address register
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x0A, address & 0xFFFF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initiate the extended read
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x0C, 0x8000);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    timeout = millis() + 100L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do  // Wait for the read to be complete
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        results = PrimaryRead(cs, 0x0C, readFlags);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        if (results != kNOERROR)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return results;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Make sure the read is not taking too long
 | 
				
			||||||
 | 
					        currentTime = millis();
 | 
				
			||||||
 | 
					        if (timeout < currentTime)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return kEXTENDEDREADTIMEOUTERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } while ((readFlags & 0x0001) != 0x0001);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Read the most significant word from the extended read data
 | 
				
			||||||
 | 
					    results = PrimaryRead(cs, 0x0E, valueMSW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Read the least significant word from the extended read data
 | 
				
			||||||
 | 
					    results = PrimaryRead(cs, 0x10, valueLSW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Combine them
 | 
				
			||||||
 | 
					    value = ((uint32_t)valueMSW << 16) + valueLSW;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return results;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ExtendedWrite
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Write to the SRAM, EEPROM, AUX or Extended Access Commands
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint16_t ExtendedWrite(uint16_t cs, uint16_t address, uint32_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t results;
 | 
				
			||||||
 | 
					    uint16_t writeFlags;
 | 
				
			||||||
 | 
					    uint32_t timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write into the extended address register
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x02, address & 0xFFFF);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write the MSW (Most significant word) into the high order write data register
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x04, (value >> 16) & 0xFFFF);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write the LSW (Least significant word) into the low order write data register
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x06, value & 0xFFFF);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Start the write process
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x08, 0x8000);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    if (results != kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return results;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If writing to the EEPROM, generate the Program
 | 
				
			||||||
 | 
					    // Pulses on Vcc
 | 
				
			||||||
 | 
					    if ((address >= 0x300) && (address < 0x320))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Send the Program Pulses
 | 
				
			||||||
 | 
					        // Need hardware which this example does not have.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    timeout = millis() + 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Wait for the write to complete
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        results = PrimaryRead(cs, 0x08, writeFlags);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        if (results != kNOERROR)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return results;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (timeout < millis())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return kEXTENDEDWRITETIMEOUTERROR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } while ((writeFlags & 0x0001) != 0x0001);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return results;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * SetProcessorStateToIdle
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Change the processor state to idle
 | 
				
			||||||
 | 
					 * This is needed to write EEPROM, change ORATE or perform certain self tests
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint16_t SetProcessorStateToIdle(uint8_t cs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t results;
 | 
				
			||||||
 | 
					    uint16_t value;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    // Write the enter idle state command into the control register
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x1F, 0x8046);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (results == kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delay(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Read the status register to see if the processor is in the idle state
 | 
				
			||||||
 | 
					        results = PrimaryRead(cs, 0x22, value);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (results == kNOERROR)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ((value & 0x00FF) != 0x0010)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return kUNABLETOCHANGEPROCESSORSTATE;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    return results;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * SetProcessorStateToRun
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Change the processor state to run
 | 
				
			||||||
 | 
					 * This is needed to process angles
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint16_t SetProcessorStateToRun(uint8_t cs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t results;
 | 
				
			||||||
 | 
					    uint16_t value;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    // Write the enter idle state command into the control register
 | 
				
			||||||
 | 
					    results = PrimaryWrite(cs, 0x1F, 0xC046);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (results == kNOERROR)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delay(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Read the status register to see if the processor is in the idle state
 | 
				
			||||||
 | 
					        results = PrimaryRead(cs, 0x22, value);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (results == kNOERROR)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ((value & 0x00FF) != 0x0011)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return kUNABLETOCHANGEPROCESSORSTATE;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    return results;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setup() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint16_t unused;
 | 
				
			||||||
 | 
					 	uint32_t flags;
 | 
				
			||||||
 | 
						uint16_t angle;
 | 
				
			||||||
 | 
						uint32_t flagsAndZeroOffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SPI.begin();
 | 
				
			||||||
 | 
					  // put your setup code here, to run once:
 | 
				
			||||||
 | 
					  Serial.begin(19200);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   while (!Serial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pinMode(SS, OUTPUT);
 | 
				
			||||||
 | 
					  digitalWrite(SS, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Make sure all of the SPI pins are
 | 
				
			||||||
 | 
					  // ready by doing a read
 | 
				
			||||||
 | 
					  //PrimaryRead(ChipSelectPin, 0x0, unused);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Unlock the device
 | 
				
			||||||
 | 
					  ExtendedWrite(ChipSelectPin, 0xFFFE, 0x27811F77);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Make sure the device is unlocked
 | 
				
			||||||
 | 
					  ExtendedRead(ChipSelectPin, 0x22, flags);
 | 
				
			||||||
 | 
					  if (!((flags & 0x0022) == 0x0020))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					      Serial.println("Device is not Unlocked");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Zero the angle
 | 
				
			||||||
 | 
					  // Extended location 0x06 contains flags in the MSW and the Zero Angle values in the LSW
 | 
				
			||||||
 | 
					  // so get both and zero out ZeroAngle
 | 
				
			||||||
 | 
					  ExtendedRead(ChipSelectPin, 0x06, flagsAndZeroOffset);
 | 
				
			||||||
 | 
					  flagsAndZeroOffset = (flagsAndZeroOffset & 0xFFFF0000);
 | 
				
			||||||
 | 
					  ExtendedWrite(ChipSelectPin, 0x06, flagsAndZeroOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Get the current angle. It is now without the ZeroAngle correction
 | 
				
			||||||
 | 
					  PrimaryRead(ChipSelectPin, 0x20, angle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Copy the read angle into location 0x5C preserving the flags
 | 
				
			||||||
 | 
					  flagsAndZeroOffset = (flagsAndZeroOffset & 0xFFFF0000) | ((angle << 4) & 0x0000FFFF);
 | 
				
			||||||
 | 
					  ExtendedWrite(ChipSelectPin, 0x06, flagsAndZeroOffset);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* uint16_t angle_read;
 | 
				
			||||||
 | 
					  Serial.println("Init Complete");
 | 
				
			||||||
 | 
					  PrimaryRead(ChipSelectPin, 0x20, angle_read);
 | 
				
			||||||
 | 
					  Serial.print("Angle= ");
 | 
				
			||||||
 | 
					  Serial.println(angle_read); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void loop() {
 | 
				
			||||||
 | 
					  uint16_t angle;
 | 
				
			||||||
 | 
					    uint16_t temperature;
 | 
				
			||||||
 | 
					    uint16_t fieldStrength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Every second, read the angle, temperature and field strength
 | 
				
			||||||
 | 
					    if (nextTime < millis())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (PrimaryRead(ChipSelectPin, 0x20, angle) == kNOERROR)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
					            if (CalculateParity(angle))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Serial.print("Angle = ");
 | 
				
			||||||
 | 
					                Serial.print((float)(angle & 0x0FFF) * 360.0 / 4096.0);
 | 
				
			||||||
 | 
					                Serial.println(" Degrees");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Serial.println("Parity error on Angle read");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Serial.println("Unable to read Angle");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (PrimaryRead(ChipSelectPin, 0x28, temperature) == kNOERROR)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Serial.print("Temperature = ");
 | 
				
			||||||
 | 
								Serial.print(((float)(temperature & 0x0FFF) / 8.0) - 273.15);
 | 
				
			||||||
 | 
								Serial.println(" C");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Serial.println("Unable to read Temperature");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (PrimaryRead(ChipSelectPin, 0x2A, fieldStrength) == kNOERROR)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Serial.print("Field Strength = ");
 | 
				
			||||||
 | 
								Serial.print(fieldStrength & 0x0FFF);
 | 
				
			||||||
 | 
								Serial.println(" Gauss");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Serial.println("Unable to read Field Strength");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nextTime = millis() + 500L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Blink the LED every half second
 | 
				
			||||||
 | 
					        if (ledOn)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            digitalWrite(LEDPin, LOW);
 | 
				
			||||||
 | 
					            ledOn = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            digitalWrite(LEDPin, HIGH);
 | 
				
			||||||
 | 
					            ledOn = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This directory is intended for PlatformIO Unit Testing and project tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unit Testing is a software testing method by which individual units of
 | 
				
			||||||
 | 
					source code, sets of one or more MCU program modules together with associated
 | 
				
			||||||
 | 
					control data, usage procedures, and operating procedures, are tested to
 | 
				
			||||||
 | 
					determine whether they are fit for use. Unit testing finds problems early
 | 
				
			||||||
 | 
					in the development cycle.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More information about PlatformIO Unit Testing:
 | 
				
			||||||
 | 
					- https://docs.platformio.org/page/plus/unit-testing.html
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					#include <AS5048A.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AS5048A angleSensor(SS, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setup()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Serial.begin(19200);
 | 
				
			||||||
 | 
						angleSensor.begin();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void loop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						delay(100);
 | 
				
			||||||
 | 
						float val = angleSensor.getRotationInDegrees();
 | 
				
			||||||
 | 
						Serial.print("\nGot rotation of: ");
 | 
				
			||||||
 | 
						Serial.println(val);
 | 
				
			||||||
 | 
						Serial.print("State: ");
 | 
				
			||||||
 | 
						angleSensor.printState();
 | 
				
			||||||
 | 
						Serial.print("Errors: ");
 | 
				
			||||||
 | 
						Serial.println(angleSensor.getErrors());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -6,13 +6,36 @@
 | 
				
			||||||
 */ 
 | 
					 */ 
 | 
				
			||||||
#include "A1335.h"
 | 
					#include "A1335.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//--- Normal Write Registers ---//
 | 
				
			||||||
 | 
					#define	EWA		(0x02U)   // Extended Write Address
 | 
				
			||||||
 | 
					#define EWD     (0x04U)   // Extended Write Data
 | 
				
			||||||
 | 
					#define EWCS    (0x08U)   // Extended Write Control and Status
 | 
				
			||||||
 | 
					#define ERA		(0x0AU)   // Extended Read Address
 | 
				
			||||||
 | 
					#define ERCS	(0x0CU)   // Extended Read Control and Status
 | 
				
			||||||
 | 
					#define ERD		(0x0EU)   // Extended Read Data
 | 
				
			||||||
 | 
					#define CTRL	(0x1EU)   // Device control
 | 
				
			||||||
 | 
					#define ANG		(0x20U)   // Current angle and related data
 | 
				
			||||||
 | 
					#define STA		(0x22U)   // Device status
 | 
				
			||||||
 | 
					#define ERR		(0x24U)  // Device error status
 | 
				
			||||||
 | 
					#define XERR	(0x26U)   // Extended error status
 | 
				
			||||||
 | 
					#define TSEN	(0x28U)   // Temperature sensor data
 | 
				
			||||||
 | 
					#define FIELD	(0x2AU)   // Magnetic field strength
 | 
				
			||||||
 | 
					#define ERM		(0x34U)   // Device error status masking
 | 
				
			||||||
 | 
					#define XERM	(0x36U)   // Extended error status masking
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//--- Extended Write Registers ---//
 | 
				
			||||||
 | 
					#define ORATE	(0xFFD0)  // Output Rate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//--- Errors ---//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define kNOERROR						0
 | 
					#define kNOERROR						0
 | 
				
			||||||
#define kPRIMARYREADERROR				1
 | 
					#define kPRIMARYREADERROR				1
 | 
				
			||||||
#define kEXTENDEDREADTIMEOUTERROR		2
 | 
					#define kEXTENDEDREADTIMEOUTERROR		2
 | 
				
			||||||
#define kPRIMARYWRITEERROR				3
 | 
					#define kPRIMARYWRITEERROR				3
 | 
				
			||||||
#define kEXTENDEDWRITETIMEOUTERROR		4
 | 
					#define kEXTENDEDWRITETIMEOUTERROR		4
 | 
				
			||||||
#define kCRCERROR						5
 | 
					#define kCRCERROR						5
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define kUNABLETOCHANGEPROCESSORSTATE	6
 | 
					#define kUNABLETOCHANGEPROCESSORSTATE	6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const uint16_t ChipSelectPin = 5;
 | 
					const uint16_t ChipSelectPin = 5;
 | 
				
			||||||
| 
						 | 
					@ -27,8 +50,11 @@ unsigned long nextTime;
 | 
				
			||||||
bool ledOn = false;
 | 
					bool ledOn = false;
 | 
				
			||||||
bool includeCRC = false;
 | 
					bool includeCRC = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool debugPrint = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SPI_S A1 = {
 | 
					struct SPI_S A1 = {
 | 
				
			||||||
	.SPI_angleSensor_n = &SPI_1,
 | 
						.SPI_angleSensor_n = NULL,
 | 
				
			||||||
 | 
						.io = NULL,
 | 
				
			||||||
	.state = 0,
 | 
						.state = 0,
 | 
				
			||||||
	.SS_pin = Angle_SS,
 | 
						.SS_pin = Angle_SS,
 | 
				
			||||||
	.tx_buffer = NULL,
 | 
						.tx_buffer = NULL,
 | 
				
			||||||
| 
						 | 
					@ -36,26 +62,46 @@ struct SPI_S A1 = {
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void angleSensor_init(struct spi_m_sync_descriptor *spi)
 | 
					void angleSensor_init(struct spi_m_sync_descriptor *spi, struct SPI_S *Sn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	spi_m_sync_get_io_descriptor(spi, &io);
 | 
						Sn->SPI_angleSensor_n = spi;
 | 
				
			||||||
	spi_m_sync_enable(spi);
 | 
						spi_m_sync_get_io_descriptor(Sn->SPI_angleSensor_n, &Sn->io);
 | 
				
			||||||
	
 | 
						spi_m_sync_enable(Sn->SPI_angleSensor_n);
 | 
				
			||||||
 | 
						gpio_set_pin_level(Sn->SS_pin, true);
 | 
				
			||||||
 | 
						if(Sn->io == NULL || Sn->SPI_angleSensor_n == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Sn->state = 4;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Sn->state = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void angleSensor_State_Machine(struct SPI_S *Sn)
 | 
					void angleSensor_State_Machine(struct SPI_S *Sn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint16_t value;
 | 
						volatile uint16_t angle;
 | 
				
			||||||
	switch(Sn->state){
 | 
						switch(Sn->state){
 | 
				
			||||||
		case 0:
 | 
							case 0:		// Default un-initialized State
 | 
				
			||||||
			angleSensor_init(Sn->SPI_angleSensor_n);
 | 
							break;
 | 
				
			||||||
			gpio_set_pin_level(Sn->SS_pin, true);
 | 
							case 1:		// State After angleSensor_init.  Configure Sensor
 | 
				
			||||||
			Sn->state++;
 | 
								Sn->state++;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
		case 1:	
 | 
							case 2:   // Syncronouse blocking read
 | 
				
			||||||
			PrimaryRead(Sn->SS_pin, 0x20, &value);
 | 
								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");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
		case 2:
 | 
							case 3:		// Continuously Read Angle (DMA)
 | 
				
			||||||
 | 
							break;	
 | 
				
			||||||
 | 
							case 4:		// Error State
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -120,43 +166,57 @@ uint8_t CalculateCRC(uint16_t input)
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * Read from the primary serial registers
 | 
					 * Read from the primary serial registers
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
uint16_t PrimaryRead(uint16_t cs, uint16_t address, uint16_t* value)
 | 
					uint16_t PrimaryRead(struct SPI_S *Sn, uint16_t address, uint16_t* value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						uint8_t in_buf[2], out_buf[2];
 | 
				
			||||||
 | 
						uint16_t returnedVal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint16_t command = ((address & ADDRESS_MASK) | READ) << 8;
 | 
						uint16_t command = ((address & ADDRESS_MASK) | READ) << 8;
 | 
				
			||||||
		gpio_set_pin_level(Angle_SS, false);
 | 
						//Split the command into two bytes
 | 
				
			||||||
 | 
						out_buf[1] = command & 0xFF;
 | 
				
			||||||
 | 
						out_buf[0] = ( command >> 8 ) & 0xFF;
 | 
				
			||||||
 | 
						gpio_set_pin_level(Sn->SS_pin, false);
 | 
				
			||||||
 | 
						transfer16(Sn, command);
 | 
				
			||||||
 | 
						gpio_set_pin_level(Sn->SS_pin, true);	
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
		struct spi_msg msg;
 | 
					 	gpio_set_pin_level(Sn->SS_pin, false);	
 | 
				
			||||||
 | 
					 	returnedVal = transfer16(Sn, command);
 | 
				
			||||||
 | 
					 	gpio_set_pin_level(Sn->SS_pin, true);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
		
 | 
					// 	printf("In_buff= ");
 | 
				
			||||||
		spi_m_sync_transfer(Sn->SPI_angleSensor_n, )
 | 
					// 	/* Print Received data by SPI Master from SPI Slave on Console */
 | 
				
			||||||
			
 | 
					// 	for (int i = 0; i < 2; i++) {
 | 
				
			||||||
		
 | 
					// 		printf("%u", in_buf[i]);
 | 
				
			||||||
        //SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //// Combine the register address and the command into one byte
 | 
					 | 
				
			||||||
        //uint16_t command = ((address & ADDRESS_MASK) | READ) << 8;
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //// take the chip select low to select the device
 | 
					 | 
				
			||||||
        //digitalWrite(cs, LOW);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //// send the device the register you want to read
 | 
					 | 
				
			||||||
        //SPI.transfer16(command);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //digitalWrite(cs, HIGH);
 | 
					 | 
				
			||||||
        //digitalWrite(cs, LOW);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //// send the command again to read the contents
 | 
					 | 
				
			||||||
        //value = SPI.transfer16(command);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //// take the chip select high to de-select
 | 
					 | 
				
			||||||
        //digitalWrite(cs, HIGH);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
        //SPI.endTransaction();
 | 
					 | 
				
			||||||
// 	}
 | 
					// 	}
 | 
				
			||||||
//
 | 
					// 	printf("\n\r");		
	*value = returnedVal;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if(debugPrint) {
 | 
				
			||||||
 | 
							printf("Returned val = %u \n\r", returnedVal);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						
 | 
				
			||||||
    return kNOERROR;
 | 
					    return kNOERROR;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t transfer16(struct SPI_S *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_angleSensor_n, &xfer);
 | 
				
			||||||
 | 
						wordRead = (uint16_t)((in_buf[0] << 8) | in_buf[1]);
 | 
				
			||||||
 | 
						return wordRead;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * PrimaryWrite
 | 
					 * PrimaryWrite
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SPI_S {
 | 
					struct SPI_S {
 | 
				
			||||||
	struct spi_m_sync_descriptor *SPI_angleSensor_n;
 | 
						struct spi_m_sync_descriptor *SPI_angleSensor_n;
 | 
				
			||||||
 | 
						struct io_descriptor *io;
 | 
				
			||||||
	uint8_t state;
 | 
						uint8_t state;
 | 
				
			||||||
	uint32_t SS_pin;
 | 
						uint32_t SS_pin;
 | 
				
			||||||
	struct spi_xfer xfer;
 | 
						struct spi_xfer xfer;
 | 
				
			||||||
| 
						 | 
					@ -22,18 +23,19 @@ struct SPI_S {
 | 
				
			||||||
struct SPI_S A1;
 | 
					struct SPI_S A1;
 | 
				
			||||||
struct io_descriptor *io;
 | 
					struct io_descriptor *io;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void angleSensor_init(struct spi_m_sync_descriptor *spi);
 | 
					void angleSensor_init(struct spi_m_sync_descriptor *spi, struct SPI_S *Sn);
 | 
				
			||||||
void angleSensor_State_Machine(struct SPI_S *Sn);
 | 
					void angleSensor_State_Machine(struct SPI_S *Sn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool CalculateParity(uint16_t input);
 | 
					bool CalculateParity(uint16_t input);
 | 
				
			||||||
uint8_t CalculateCRC(uint16_t input);
 | 
					uint8_t CalculateCRC(uint16_t input);
 | 
				
			||||||
uint16_t PrimaryRead(uint16_t cs, uint16_t address, uint16_t* value);
 | 
					uint16_t PrimaryRead(struct SPI_S *Sn, uint16_t address, uint16_t* value);
 | 
				
			||||||
uint16_t PrimaryWrite(uint16_t cs, 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 ExtendedRead(uint16_t cs, uint16_t address, uint32_t value);
 | 
				
			||||||
uint16_t ExtendedWrite(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 SetProcessorStateToRun(uint8_t cs);
 | 
				
			||||||
uint16_t SetProcessorStateToIdle(uint8_t cs);
 | 
					uint16_t SetProcessorStateToIdle(uint8_t cs);
 | 
				
			||||||
uint16_t SetProcessorStateToRun(uint8_t cs);
 | 
					uint16_t SetProcessorStateToRun(uint8_t cs);
 | 
				
			||||||
 | 
					uint16_t transfer16(struct SPI_S *Sn, uint16_t value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* A1335_H_ */
 | 
					#endif /* A1335_H_ */
 | 
				
			||||||
| 
						 | 
					@ -20,10 +20,10 @@
 | 
				
			||||||
    <OverrideVtor>false</OverrideVtor>
 | 
					    <OverrideVtor>false</OverrideVtor>
 | 
				
			||||||
    <CacheFlash>true</CacheFlash>
 | 
					    <CacheFlash>true</CacheFlash>
 | 
				
			||||||
    <ProgFlashFromRam>true</ProgFlashFromRam>
 | 
					    <ProgFlashFromRam>true</ProgFlashFromRam>
 | 
				
			||||||
    <RamSnippetAddress />
 | 
					    <RamSnippetAddress>0x20000000</RamSnippetAddress>
 | 
				
			||||||
    <UncachedRange />
 | 
					    <UncachedRange />
 | 
				
			||||||
    <preserveEEPROM>true</preserveEEPROM>
 | 
					    <preserveEEPROM>true</preserveEEPROM>
 | 
				
			||||||
    <OverrideVtorValue />
 | 
					    <OverrideVtorValue>exception_table</OverrideVtorValue>
 | 
				
			||||||
    <BootSegment>2</BootSegment>
 | 
					    <BootSegment>2</BootSegment>
 | 
				
			||||||
    <ResetRule>0</ResetRule>
 | 
					    <ResetRule>0</ResetRule>
 | 
				
			||||||
    <eraseonlaunchrule>0</eraseonlaunchrule>
 | 
					    <eraseonlaunchrule>0</eraseonlaunchrule>
 | 
				
			||||||
| 
						 | 
					@ -365,7 +365,6 @@
 | 
				
			||||||
  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
 | 
					  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
 | 
				
			||||||
  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
 | 
					  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
 | 
				
			||||||
  <armgcc.compiler.miscellaneous.OtherFlags>-std=gnu99 -mfloat-abi=softfp -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
 | 
					  <armgcc.compiler.miscellaneous.OtherFlags>-std=gnu99 -mfloat-abi=softfp -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
 | 
				
			||||||
  <armgcc.linker.general.UseNewlibNano>True</armgcc.linker.general.UseNewlibNano>
 | 
					 | 
				
			||||||
  <armgcc.linker.libraries.Libraries>
 | 
					  <armgcc.linker.libraries.Libraries>
 | 
				
			||||||
    <ListValues>
 | 
					    <ListValues>
 | 
				
			||||||
      <Value>libm</Value>
 | 
					      <Value>libm</Value>
 | 
				
			||||||
| 
						 | 
					@ -377,6 +376,7 @@
 | 
				
			||||||
    </ListValues>
 | 
					    </ListValues>
 | 
				
			||||||
  </armgcc.linker.libraries.LibrarySearchPaths>
 | 
					  </armgcc.linker.libraries.LibrarySearchPaths>
 | 
				
			||||||
  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
 | 
					  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
 | 
				
			||||||
 | 
					  <armgcc.linker.memorysettings.ExternalRAM />
 | 
				
			||||||
  <armgcc.linker.miscellaneous.LinkerFlags>-Tsame54p20a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
 | 
					  <armgcc.linker.miscellaneous.LinkerFlags>-Tsame54p20a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
 | 
				
			||||||
  <armgcc.assembler.general.IncludePaths>
 | 
					  <armgcc.assembler.general.IncludePaths>
 | 
				
			||||||
    <ListValues>
 | 
					    <ListValues>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ static void task1_cb(const struct timer_task *const timer_task)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TIMER_0_init(void)
 | 
					void TIMER_0_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TIMER_0_task1.interval = 10;
 | 
						TIMER_0_task1.interval = 100;
 | 
				
			||||||
	TIMER_0_task1.cb       = task1_cb;
 | 
						TIMER_0_task1.cb       = task1_cb;
 | 
				
			||||||
	TIMER_0_task1.mode     = TIMER_TASK_REPEAT;
 | 
						TIMER_0_task1.mode     = TIMER_TASK_REPEAT;
 | 
				
			||||||
	timer_add_task(&TIMER_0, &TIMER_0_task1);
 | 
						timer_add_task(&TIMER_0, &TIMER_0_task1);
 | 
				
			||||||
| 
						 | 
					@ -88,14 +88,15 @@ int main(void)
 | 
				
			||||||
	/* Initializes MCU, drivers and middleware */
 | 
						/* Initializes MCU, drivers and middleware */
 | 
				
			||||||
	atmel_start_init();
 | 
						atmel_start_init();
 | 
				
			||||||
	/* Initialize SPI master IO and Callback  */
 | 
						/* Initialize SPI master IO and Callback  */
 | 
				
			||||||
	spi_master_init();
 | 
						//spi_master_init();
 | 
				
			||||||
 | 
						angleSensor_init(&SPI_1, &A1);
 | 
				
			||||||
	TIMER_0_init();
 | 
						TIMER_0_init();
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	spi_m_dma_enable(&SPI_0);
 | 
						//spi_m_dma_enable(&SPI_0);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	/* Start SPI Master data transfer using DMA */
 | 
						/* Start SPI Master data transfer using DMA */
 | 
				
			||||||
	//spi_master_rx(rx_buffer, BUFFER_LEN);
 | 
						//spi_master_rx(rx_buffer, BUFFER_LEN);
 | 
				
			||||||
	spi_master_tx(tx_buffer, BUFFER_LEN);
 | 
						//spi_master_tx(tx_buffer, BUFFER_LEN);
 | 
				
			||||||
	/* Start SPI Master data reception using DMA */
 | 
						/* Start SPI Master data reception using DMA */
 | 
				
			||||||
	//spi_master_rx(tx_buffer, BUFFER_LEN);
 | 
						//spi_master_rx(tx_buffer, BUFFER_LEN);
 | 
				
			||||||
	printf("Init Complete\n\r");
 | 
						printf("Init Complete\n\r");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue