/* * 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); } }