Program Listing for File TLE5012b.cpp
↰ Return to documentation for file (src/corelib/TLE5012b.cpp)
#include "TLE5012b.hpp"
#include "Arduino.h"
using namespace tle5012;
//-----------------------------------------------------------------------------
// none_class functions
uint8_t getFirstByte(uint16_t twoByteWord)
{
return ((uint8_t) (twoByteWord >> 8));
}
uint8_t getSecondByte(uint16_t twoByteWord)
{
return ((uint8_t) twoByteWord);
}
uint8_t crc8(uint8_t *data, uint8_t length)
{
uint32_t crc;
int16_t i, bit;
crc = CRC_SEED;
for (i = 0; i < length; i++)
{
crc ^= data[i];
for (bit = 0; bit < 8; bit++)
{
if ((crc & 0x80) != 0)
{
crc <<= 1;
crc ^= CRC_POLYNOMIAL;
}else{
crc <<= 1;
}
}
}
return ((~crc) & CRC_SEED);
}
uint8_t crcCalc(uint8_t* crcData, uint8_t length)
{
return (crc8(crcData, length));
}
double calculateAngleSpeed(double angRange, int16_t rawAngleSpeed, uint16_t firMD, uint16_t predictionVal)
{
double microsecToSec = 0.000001;
double firMDVal;
switch ( firMD )
{
case 1:
firMDVal = 42.7;
break;
case 2:
firMDVal = 85.3;
break;
case 3:
firMDVal = 170.6;
break;
default:
firMDVal = 21.3;
}
double dividend = angRange * (double)rawAngleSpeed / (POW_2_15 * microsecToSec);
double divisor = (double)predictionVal * firMDVal;
double finalAngleSpeed = dividend / divisor;
return ( finalAngleSpeed);
}
// end none class functions
//-----------------------------------------------------------------------------
Tle5012b::Tle5012b():reg(this)
{
sBus = NULL;
en = NULL;
safetyWord = 0;
mSlave = TLE5012B_S0;
}
Tle5012b::~Tle5012b()
{
end();
en = NULL;
sBus = NULL;
}
void Tle5012b::end(void)
{
disableSensor();
sBus->deinit();
}
void Tle5012b::enableSensor()
{
if (en != NULL) {
en->enable();
}
}
void Tle5012b::disableSensor()
{
if (en != NULL) {
en->disable();
}
}
//-----------------------------------------------------------------------------
// begin generic data transfer functions
errorTypes Tle5012b::readFromSensor(uint16_t command, uint16_t &data, updTypes upd, safetyTypes safe)
{
errorTypes checkError = NO_ERROR;
_command[0] = READ_SENSOR | command | upd | safe;
uint16_t _received[MAX_REGISTER_MEM] = {0};
sBus->sendReceive(_command, 1, _received, 2);
data = _received[0];
if (safe == SAFE_high)
{
checkError = checkSafety(_received[1], _command[0], &_received[0], 1);
if (checkError != NO_ERROR)
{
data = 0;
}
}
return (checkError);
}
errorTypes Tle5012b::readMoreRegisters(uint16_t command, uint16_t data[], updTypes upd, safetyTypes safe)
{
errorTypes checkError = NO_ERROR;
_command[0] = READ_SENSOR | command | upd | safe;
uint16_t _received[MAX_REGISTER_MEM] = {0};
uint16_t _recDataLength = (_command[0] & (0x000F)); // Number of registers to read
sBus->sendReceive(_command, 1, _received, _recDataLength + safe);
memcpy(data, _received, (_recDataLength)* sizeof(uint16_t));
if (safe == SAFE_high)
{
checkError = checkSafety(_received[_recDataLength], _command[0], _received, _recDataLength);
if (checkError != NO_ERROR)
{
data = 0;
}
}
return (checkError);
}
errorTypes Tle5012b::writeToSensor(uint16_t command, uint16_t dataToWrite, bool changeCRC)
{
uint16_t safety = 0;
_command[0] = WRITE_SENSOR | command | SAFE_high;
_command[1] = dataToWrite;
sBus->sendReceive(_command, 2, &safety, 1);
errorTypes checkError = checkSafety(safety, _command[0], &_command[1], 1);
//if we write to a register, which changes the CRC.
if (changeCRC)
{
checkError = regularCrcUpdate();
}
return (checkError);
}
errorTypes Tle5012b::writeTempCoeffUpdate(uint16_t dataToWrite)
{
uint16_t safety = 0;
uint16_t readreg = 0;
sBus->triggerUpdate();
_command[0] = WRITE_SENSOR | reg.REG_TCO_Y | SAFE_high;
_command[1] = dataToWrite;
sBus->sendReceive(_command, 2, &safety, 1);
errorTypes checkError = checkSafety(safety, _command[0], &_command[1], 1);
//
checkError = readStatus(readreg);
if (readreg & 0x0008)
{
checkError = regularCrcUpdate();
}
return (checkError);
}
// end generic data transfer functions
//-----------------------------------------------------------------------------
// begin CRC functions
errorTypes Tle5012b::checkSafety(uint16_t safety, uint16_t command, uint16_t* readreg, uint16_t length)
{
errorTypes errorCheck;
safetyWord = safety;
if (!((safety) & SYSTEM_ERROR_MASK))
{
errorCheck = SYSTEM_ERROR;
// resetSafety();
} else if (!((safety) & INTERFACE_ERROR_MASK))
{
errorCheck = INTERFACE_ACCESS_ERROR;
// resetSafety();
} else if (!((safety) & INV_ANGLE_ERROR_MASK))
{
errorCheck = INVALID_ANGLE_ERROR;
// resetSafety();
}else{
resetSafety();
const uint16_t lengthOfTemp = MAX_REGISTER_MEM * 2 + 2;
uint8_t temp[lengthOfTemp];
temp[0] = getFirstByte(command);
temp[1] = getSecondByte(command);
for (uint16_t i = 0; i < length; i++)
{
temp[2 + 2 * i] = getFirstByte(readreg[i]);
temp[2 + 2 * i + 1] = getSecondByte(readreg[i]);
}
uint8_t crcReceivedFinal = getSecondByte(safety);
uint8_t crc = crcCalc(temp, length * 2 + 2);
if (crc == crcReceivedFinal)
{
errorCheck = NO_ERROR;
}else{
errorCheck = CRC_ERROR;
resetSafety();
}
}
return (errorCheck);
}
void Tle5012b::resetSafety()
{
uint16_t command = READ_SENSOR + SAFE_high;
uint16_t receive[4];
sBus->triggerUpdate();
sBus->sendReceive(&command, 1, receive, 3);
}
errorTypes Tle5012b::resetFirmware()
{
uint16_t rawData = 0x401;
errorTypes status = writeActivationStatus(rawData);
return (status);
}
errorTypes Tle5012b::regularCrcUpdate()
{
readBlockCRC();
uint8_t temp[16];
for (uint8_t i = 0; i < CRC_NUM_REGISTERS; i++)
{
temp[2 * i] = getFirstByte(_registers[i]);
temp[(2 * i) + 1] = getSecondByte(_registers[i]);
}
uint8_t crc = crcCalc(temp, 15);
uint16_t firstTempByte = (uint16_t) temp[14];
uint16_t secondTempByte = (uint16_t) crc;
uint16_t valToSend = (firstTempByte << 8) | secondTempByte;
_registers[7] = valToSend;
return (writeTempCoeffUpdate(valToSend));
}
// end CRC functions
//-----------------------------------------------------------------------------
// begin read functions
errorTypes Tle5012b::readBlockCRC()
{
_command[0] = READ_BLOCK_CRC;
_registers[CRC_NUM_REGISTERS + 1] = {0}; // Number of CRC Registers + 1 Register for Safety word
sBus->sendReceive(_command, 1, _registers, CRC_NUM_REGISTERS+1);
errorTypes checkError = checkSafety(_registers[8], READ_BLOCK_CRC, _registers, CRC_NUM_REGISTERS);
resetSafety();
return (checkError);
}
errorTypes Tle5012b::readStatus(uint16_t &data, updTypes upd, safetyTypes safe)
{
return (readFromSensor(reg.REG_STAT, data, upd, safe));
}
errorTypes Tle5012b::readActivationStatus(uint16_t &data, updTypes upd, safetyTypes safe)
{
return (readFromSensor(reg.REG_ACSTAT, data, upd, safe));
}
errorTypes Tle5012b::readSIL(uint16_t &data)
{
return (readFromSensor(reg.REG_SIL, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readIntMode1(uint16_t &data)
{
return (readFromSensor(reg.REG_MOD_1, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readIntMode2(uint16_t &data)
{
return (readFromSensor(reg.REG_MOD_2, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readIntMode3(uint16_t &data)
{
return (readFromSensor(reg.REG_MOD_3, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readIntMode4(uint16_t &data)
{
return (readFromSensor(reg.REG_MOD_4, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readOffsetX(uint16_t &data)
{
return (readFromSensor(reg.REG_OFFX, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readOffsetY(uint16_t &data)
{
return (readFromSensor(reg.REG_OFFY, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readSynch(uint16_t &data)
{
return (readFromSensor(reg.REG_SYNCH, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readIFAB(uint16_t &data)
{
return (readFromSensor(reg.REG_IFAB, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readTempCoeff(uint16_t &data)
{
return (readFromSensor(reg.REG_TCO_Y, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readTempDMag(uint16_t &data)
{
return (readFromSensor(reg.REG_D_MAG, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readTempIIFCnt(uint16_t &data)
{
return (readFromSensor(reg.REG_IIF_CNT, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readTempRaw(uint16_t &data)
{
return (readFromSensor(reg.REG_T_RAW, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readTempT25(uint16_t &data)
{
return (readFromSensor(reg.REG_T25O, data, UPD_low, SAFE_high));
}
errorTypes Tle5012b::readRawX(int16_t &data)
{
uint16_t rawData = 0;
errorTypes status = readFromSensor(reg.REG_ADC_X, rawData);
if (status != NO_ERROR)
{
return (status);
}
data = rawData;
return (status);
}
errorTypes Tle5012b::readRawY(int16_t &data)
{
uint16_t rawData = 0;
errorTypes status = readFromSensor(reg.REG_ADC_Y, rawData);
if (status != NO_ERROR)
{
return (status);
}
data = rawData;
return (status);
}
// end read functions
//-----------------------------------------------------------------------------
// begin get functions
errorTypes Tle5012b::getAngleValue(double &angleValue)
{
int16_t rawAngleValue = 0;
return (getAngleValue(angleValue, rawAngleValue, UPD_low, SAFE_high));
}
errorTypes Tle5012b::getAngleValue(double &angleValue, int16_t &rawAngleValue, updTypes upd, safetyTypes safe)
{
uint16_t rawData = 0;
errorTypes status = readFromSensor(reg.REG_AVAL, rawData, upd, safe);
if (status != NO_ERROR)
{
return (status);
}
rawData = (rawData & (DELETE_BIT_15));
//check if the value received is positive or negative
if (rawData & CHECK_BIT_14)
{
rawData = rawData - CHANGE_UINT_TO_INT_15;
}
rawAngleValue = rawData;
angleValue = (ANGLE_360_VAL / POW_2_15) * ((double) rawAngleValue);
return (status);
}
errorTypes Tle5012b::getTemperature(double &temperature)
{
int16_t rawTemp = 0;
return (getTemperature(temperature, rawTemp, UPD_low, SAFE_high));
}
errorTypes Tle5012b::getTemperature(double &temperature, int16_t &rawTemp, updTypes upd, safetyTypes safe)
{
uint16_t rawData = 0;
errorTypes status = readFromSensor(reg.REG_FSYNC, rawData, upd, safe);
if (status != NO_ERROR)
{
return (status);
}
rawData = (rawData & (DELETE_7BITS));
//check if the value received is positive or negative
if (rawData & CHECK_BIT_9)
{
rawData = rawData - CHANGE_UNIT_TO_INT_9;
}
rawTemp = rawData;
temperature = (rawTemp + TEMP_OFFSET) / (TEMP_DIV);
return (status);
}
errorTypes Tle5012b::getNumRevolutions(int16_t &numRev, updTypes upd, safetyTypes safe)
{
uint16_t rawData = 0;
errorTypes status = readFromSensor(reg.REG_AREV, rawData, upd, safe);
if (status != NO_ERROR)
{
return (status);
}
rawData = (rawData & (DELETE_7BITS));
//check if the value received is positive or negative
if (rawData & CHECK_BIT_9)
{
rawData = rawData - CHANGE_UNIT_TO_INT_9;
}
numRev = rawData;
return (status);
}
errorTypes Tle5012b::getAngleSpeed(double &finalAngleSpeed)
{
int16_t rawSpeed = 0;
return (getAngleSpeed(finalAngleSpeed, rawSpeed, UPD_low, SAFE_high));
}
errorTypes Tle5012b::getAngleSpeed(double &finalAngleSpeed, int16_t &rawSpeed, updTypes upd, safetyTypes safe)
{
const int8_t numOfData = 0x7;
uint16_t rawData[numOfData] = {};
errorTypes status = readMoreRegisters(reg.REG_ASPD + numOfData, rawData, upd, safe);
if (status != NO_ERROR)
{
return (status);
}
// Prepare raw speed
rawSpeed = rawData[0];
rawSpeed = (rawSpeed & (DELETE_BIT_15));
// check if the value received is positive or negative
if (rawSpeed & CHECK_BIT_14)
{
rawSpeed = rawSpeed - CHANGE_UINT_TO_INT_15;
}
// Prepare firMD
uint16_t firMD = rawData[3];
firMD >>= 14;
// Prepare intMode2Prediction
uint16_t intMode2Prediction = rawData[5];
if (intMode2Prediction & 0x0004)
{
intMode2Prediction = 3;
}else{
intMode2Prediction = 2;
}
// Prepare angle range
uint16_t rawAngleRange = rawData[5];
rawAngleRange &= GET_BIT_14_4;
rawAngleRange >>= 4;
double angleRange = ANGLE_360_VAL * (POW_2_7 / (double) (rawAngleRange));
//checks the value of fir_MD according to which the value in the calculation of the speed will be determined
//according to if prediction is enabled then, the formula for speed changes
finalAngleSpeed = calculateAngleSpeed(angleRange, rawSpeed, firMD, intMode2Prediction);
return (status);
}
errorTypes Tle5012b::getAngleRange(double &angleRange)
{
uint16_t rawData = 0;
errorTypes status = readIntMode2(rawData);
if (status != NO_ERROR)
{
return (status);
}
//Angle Range is stored in bytes 14 - 4, so you have to do this bit shifting to get the right value
rawData &= GET_BIT_14_4;
rawData >>= 4;
angleRange = ANGLE_360_VAL * (POW_2_7 / (double) (rawData));
return (status);
}
// end get functions
//-----------------------------------------------------------------------------
// begin write functions
errorTypes Tle5012b::writeIntMode2(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_MOD_2, dataToWrite, true));
}
errorTypes Tle5012b::writeIntMode3(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_MOD_3, dataToWrite, true));
}
errorTypes Tle5012b::writeOffsetX(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_OFFX, dataToWrite, true));
}
errorTypes Tle5012b::writeOffsetY(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_OFFY, dataToWrite, true));
}
errorTypes Tle5012b::writeSynch(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_SYNCH, dataToWrite, true));
}
errorTypes Tle5012b::writeIFAB(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_IFAB, dataToWrite, true));
}
errorTypes Tle5012b::writeIntMode4(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_MOD_4, dataToWrite, true));
}
errorTypes Tle5012b::writeTempCoeff(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_TCO_Y, dataToWrite, true));
}
errorTypes Tle5012b::writeActivationStatus(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_ACSTAT, dataToWrite, false));
}
errorTypes Tle5012b::writeIntMode1(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_MOD_1, dataToWrite, false));
}
errorTypes Tle5012b::writeSIL(uint16_t dataToWrite)
{
return (writeToSensor(reg.REG_SIL, dataToWrite, false));
}
errorTypes Tle5012b::writeSlaveNumber(uint16_t dataToWrite)
{
return(writeToSensor(WRITE_SENSOR, dataToWrite, false));
}
// end write functions
errorTypes Tle5012b::readRegMap()
{
errorTypes status;
sBus->triggerUpdate();
for (int8_t i = 0; i < MAX_NUM_REG; i++)
{
status = readFromSensor(reg.addrFields[i].regAddress, reg.regMap[i], UPD_low, SAFE_high);
}
return (status);
}
errorTypes Tle5012b::writeInterfaceType(Reg::interfaceType_t iface)
{
uint16_t rawData = 0;
errorTypes status = readIntMode4(rawData);
if (status != NO_ERROR) {
return (status);
}
rawData &= ~(1UL << 0);
rawData &= ~(1UL << 1);
rawData = rawData | iface;
status = writeIntMode4(rawData);
return (status);
}
errorTypes Tle5012b::setCalibration(Reg::calibrationMode_t calMode)
{
uint16_t rawData = 0;
errorTypes status = readIntMode2(rawData);
if (status != NO_ERROR) {
return (status);
}
rawData &= ~(1UL << 0);
rawData &= ~(1UL << 1);
rawData = rawData | calMode;
status = writeIntMode2(rawData);
return (status);
}
// end register functions