C-Libs/ALS31313.c
2021-07-01 11:55:32 +00:00

399 lines
11 KiB
C

/*
* ALS31313.c
*
* Created on: 8 Apr 2021
* Author: angoosh
*
* Datasheet: https://www.allegromicro.com/~/media/Files/Datasheets/ALS31313-Datasheet.ashx
*/
#include "ALS31313.h"
void Enable_Setting_Modification();
uint32_t Modify_Hall_EEPROM_Settings(int, uint32_t, ACCESS);
uint32_t Modify_Hall_Register_Settings(int, uint32_t, ACCESS);
int readHallData(int*, float*);
double readDegrees(AXIS_PAIR);
void Enable_Setting_Modification(){
uint8_t address = 0x35;
int value = 0x2C413534;
uint8_t registerData[4];
registerData[0] = 0x2C;
registerData[1] = 0x41;
registerData[2] = 0x35;
registerData[3] = 0x34;
sendI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
}
/* @brief Settings 0-19
* 0: 3bit - BW select
* 1: 2bit - Hall mode
* 2: 1bit - I2C CRC Rnable
* 3: 1bit - Disable Slave ADC
* 4: 7bit - Slave Address
* 5: 1bit - I2C Threshold
* 6: 3bit - Axes Channel Enable
* 7: 1bit - INT Latch Enable
* 8: 1bit - Signed INT Enable
* 9: 1bit - INT Mode
* 10: 1bit - INT EEPROM Status
* 11: 1bit - INT EEPROM Enable
* 12: 3bit - Axes INT Enable
* 13: 6bit - Z INT Threshold
* 14: 6bit - Y INT Threshold
* 15: 6bit - X INT Threshold
* 16: 5bit - 0x02 Customer EEPROM
* 17: 26bit - 0x0D Customer EEPROM
* 18: 26bit - 0x0E Customer EEPROM
* 19: 26bit - 0x0F Customer EEPROM
* @param setting number
* @param value to write, if reading it doesn't matter
* @param READ/WRITE
* @retval read desired value of memory block, 1 if write successful or 0 if error
*/
uint32_t Modify_Hall_EEPROM_Settings(int setting, uint32_t value, ACCESS rw){
int address, returnVal;
uint8_t registerData[4];
if((setting < 8) || (setting == 16)){
address = 0x02;
}
else if(setting < 16){
address = 0x03;
}
else if((setting > 16)&&(setting < 20)){
address = 0x0D + (setting - 17);
}
if(rw == READ){
//read 32bit data (eeprom cell)
SendReadI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
if(setting == 0){
returnVal = registerData[1];
returnVal &= 0xE0;
return returnVal >> 5;
}
else if(setting == 1){
returnVal = registerData[1];
returnVal &= 0x18;
return returnVal >> 3;
}
else if(setting == 2){
returnVal = registerData[1];
returnVal &= 0x04;
return returnVal >> 2;
}
else if(setting == 3){
returnVal = registerData[1];
returnVal &= 0x02;
return returnVal >> 1;
}
else if(setting == 4){
uint8_t returnVal_MSB = registerData[1];
uint8_t returnVal_LSB = registerData[2];
returnVal_MSB &= 0x01;
returnVal_LSB &= 0xFC;
returnVal = returnVal_MSB << 6;
returnVal += returnVal_LSB >> 2;
return returnVal;
}
else if(setting == 5){
returnVal = registerData[2];
returnVal &= 0x02;
return returnVal >> 1;
}
else if(setting == 6){
uint8_t returnVal_MSB = registerData[2];
uint8_t returnVal_LSB = registerData[3];
returnVal_MSB &= 0x01;
returnVal_LSB &= 0xC0;
returnVal = returnVal_MSB << 2;
returnVal += returnVal_LSB >> 6;
return returnVal;
}
else if(setting == 7){
returnVal = registerData[3];
returnVal &= 0x10;
return returnVal >> 4;
}
else if(setting == 16){
returnVal = registerData[3];
returnVal &= 0x0F;
return returnVal;
}
else if(setting == 8){
returnVal = registerData[0];
returnVal &= 0x01;
return returnVal;
}
else if(setting == 9){
returnVal = registerData[1];
returnVal &= 0x80;
return returnVal >> 7;
}
else if(setting == 10){
returnVal = registerData[1];
returnVal &= 0x40;
return returnVal >> 6;
}
else if(setting == 11){
returnVal = registerData[1];
returnVal &= 0x20;
return returnVal >> 5;
}
else if(setting == 12){
returnVal = registerData[1];
returnVal &= 0x1C;
return returnVal >> 2;
}
else if(setting == 13){
uint8_t returnVal_MSB = registerData[1];
uint8_t returnVal_LSB = registerData[2];
returnVal_MSB &= 0x03;
returnVal_LSB &= 0xF0;
returnVal = returnVal_MSB << 4;
returnVal += returnVal_LSB >> 4;
return returnVal;
}
else if(setting == 14){
uint8_t returnVal_MSB = registerData[2];
uint8_t returnVal_LSB = registerData[3];
returnVal_MSB &= 0x0F;
returnVal_LSB &= 0xC0;
returnVal = returnVal_MSB << 2;
returnVal += returnVal_LSB >> 6;
return returnVal;
}
else if(setting == 15){
returnVal = registerData[3];
returnVal &= 0x3F;
return returnVal;
}
else if(setting >= 17){
uint8_t returnVal_MSB = registerData[0];
uint8_t returnVal_LMSB = registerData[1];
uint8_t returnVal_MLSB = registerData[2];
uint8_t returnVal_LSB = registerData[3];
returnVal_MSB &= 0x01;
returnVal = returnVal_MSB << 24;
returnVal += returnVal_LMSB << 16;
returnVal += returnVal_MLSB << 8;
returnVal += returnVal_LSB;
return returnVal;
}
}
else{
//read 32bit data (eeprom cell)
SendReadI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
if(setting == 0){
registerData[1] = ((registerData[1] & ~0xE0) | (value << 5));
}
else if(setting == 1){
registerData[1] = ((registerData[1] & ~0x18) | (value << 3));
}
else if(setting == 2){
registerData[1] = ((registerData[1] & ~0x04) | (value << 2));
}
else if(setting == 3){
registerData[1] = ((registerData[1] & ~0x02) | (value << 1));
}
else if(setting == 4){
uint8_t returnVal_MSB = (value >> 6);
uint8_t returnVal_LSB = (value << 2);
registerData[1] = ((registerData[1] & ~0x01) | (returnVal_MSB << 0));
registerData[2] = ((registerData[2] & ~0xFC) | (returnVal_LSB << 0));
}
else if(setting == 5){
registerData[2] = ((registerData[2] & ~0x02) | (value << 1));
}
else if(setting == 6){
uint8_t returnVal_MSB = (value >> 2);
uint8_t returnVal_LSB = (value << 6);
registerData[2] = ((registerData[2] & ~0x01) | (returnVal_MSB << 0));
registerData[3] = ((registerData[3] & ~0xC0) | (returnVal_LSB << 0));
}
else if(setting == 7){
registerData[3] = ((registerData[3] & ~0x10) | (value << 4));
}
else if(setting == 16){
registerData[3] = ((registerData[3] & ~0x0F) | (value << 0));
}
else if(setting == 8){
registerData[0] = ((registerData[0] & ~0x01) | (value << 0));
}
else if(setting == 9){
registerData[1] = ((registerData[1] & ~0x80) | (value << 7));
}
else if(setting == 10){
registerData[1] = ((registerData[1] & ~0x40) | (value << 6));
}
else if(setting == 11){
registerData[1] = ((registerData[1] & ~0x20) | (value << 5));
}
else if(setting == 12){
registerData[1] = ((registerData[1] & ~0x1C) | (value << 2));
}
else if(setting == 13){
uint8_t returnVal_MSB = (value >> 4);
uint8_t returnVal_LSB = (value << 4);
registerData[1] = ((registerData[1] & ~0x03) | (returnVal_MSB << 0));
registerData[2] = ((registerData[2] & ~0xF0) | (returnVal_LSB << 0));
}
else if(setting == 14){
uint8_t returnVal_MSB = (value >> 2);
uint8_t returnVal_LSB = (value << 6);
registerData[2] = ((registerData[2] & ~0x0F) | (returnVal_MSB << 0));
registerData[3] = ((registerData[3] & ~0xC0) | (returnVal_LSB << 0));
}
else if(setting == 15){
registerData[3] = ((registerData[3] & ~0x3F) | (value << 0));
}
else if(setting >= 17){
uint8_t returnVal_MSB = (value >> 24) & 0x01;
uint8_t returnVal_LMSB = (value >> 16) & 0xFF;
uint8_t returnVal_MLSB = (value >> 8) & 0xFF;
uint8_t returnVal_LSB = (value & 0xFF);
registerData[0] = ((registerData[0] & ~0xFF) | (returnVal_MSB << 0));
registerData[1] = ((registerData[1] & ~0xFF) | (returnVal_LMSB << 0));
registerData[2] = ((registerData[2] & ~0xFF) | (returnVal_MLSB << 0));
registerData[3] = ((registerData[3] & ~0xFF) | (returnVal_LSB << 0));
}
//write modified data to eeprom
sendI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
return 1;
}
return 0;
}
/* @brief Settings 0-2
* 0: 3bit - Low-Power Mode - Count Max
* 1: 2bit - I2C Loop-Mode
* 2: 2bit - Sleep
* @param setting number
* @param value to write, if reading it doesn't matter
* @param READ/WRITE
* @retval read desired value of memory block, 1 if write successful or 0 if error
*/
uint32_t Modify_Hall_Register_Settings(int setting, uint32_t value, ACCESS rw){
int address, returnVal;
uint8_t registerData[4];
address = 0x27;
if(rw == READ){
//read 32bit data (eeprom cell)
SendReadI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
if(setting == 0){
returnVal = registerData[3];
returnVal &= 0x70;
return returnVal >> 4;
}
else if(setting == 1){
returnVal = registerData[3];
returnVal &= 0x0C;
return returnVal >> 2;
}
else if(setting == 2){
returnVal = registerData[3];
returnVal &= 0x03;
return returnVal;
}
}
else{
//read 32bit data (eeprom cell)
SendReadI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
if(setting == 0){
registerData[3] = ((registerData[3] & ~0x70) | (value << 4));
}
else if(setting == 1){
registerData[3] = ((registerData[3] & ~0x0C) | (value << 2));
}
else if(setting == 2){
registerData[3] = ((registerData[3] & ~0x03) | (value << 0));
}
//write modified data to eeprom
sendI2CMaster(HALL_I2C_ADDR, address, registerData, 4, false);
return 1;
}
return 0;
}
/**
* @brief Read sensoric data from ALS31313
* @param int array of min size 3, stores x, y, z gauss value in this order
* @param float array of min size 1, temperature of the sensor in C
* @retval Hall Mode Status - 0 = Single-Ended, 1 = Differential, 2 = Common
*/
int readHallData(int *xyz, float *temp){
uint8_t registerData[8];
int16_t x, y, z;
int x_raw, y_raw, z_raw, temp_raw;
int x_g, y_g, z_g;
float tempr;
//read registers 0x28 and 0x29 respectively
SendReadI2CMaster(HALL_I2C_ADDR, 0x28, registerData, 8, false);
x_raw = registerData[0] << 4;
y_raw = registerData[1] << 4;
z_raw = registerData[2] << 4;
temp_raw = (registerData[3] & 0x3F) << 6;
x_raw += (registerData[5] & 0x0F);
y_raw += (registerData[6] & 0xF0) >> 4;
z_raw += (registerData[6] & 0x0F);
temp_raw += (registerData[7] & 0x3F);
x = (x_raw & 0x0800) ? (x_raw | 0xf800) : x_raw;
y = (y_raw & 0x0800) ? (y_raw | 0xf800) : y_raw;
z = (z_raw & 0x0800) ? (z_raw | 0xf800) : z_raw;
//convert raw data to gauss and temperature
x_g = x / LSB_GAUSS;
y_g = y / LSB_GAUSS;
z_g = z / LSB_GAUSS;
tempr = (((float)302*((float)temp_raw-(float)1708))/(float)4096);
temp[0] = tempr;
xyz[0] = x_g;
xyz[1] = y_g;
xyz[2] = z_g;
return ((registerData[7] & 0xC0) >> 6);
}
/**
* @brief Read degrees from ALS31313
* @param what axes to read: XY, XZ, YZ
* @retval degrees
*/
double readDegrees(AXIS_PAIR pair){
float temp;
int xyz[3];
readHallData(xyz, &temp);
if(pair == XY){
return ((atan2(xyz[1],xyz[0])*(180/3.14159))+180);
}
else if(pair == XZ){
return ((atan2(xyz[2],xyz[0])*(180/3.14159))+180);
}
else{
return ((atan2(xyz[1],xyz[2])*(180/3.14159))+180);
}
}