#include "AP_BattMonitor_SMBus.h" #define AP_BATTMONITOR_SMBUS_PEC_POLYNOME 0x07 // Polynome for CRC generation #define BATTMONITOR_SMBUS_TEMP 0x08 // temperature register // reads the temperature word from the battery // returns true if the read was successful bool AP_BattMonitor_SMBus::read_temp(void) { uint16_t data; if (read_word(BATTMONITOR_SMBUS_TEMP, data)) { _state.temperature_time = AP_HAL::millis(); _state.temperature = ((float)(data - 2731)) * 0.1f; return true; } return false; } // read word from register // returns true if read was successful, false if failed bool AP_BattMonitor_SMBus::read_word(uint8_t reg, uint16_t& data) const { // buffer to hold results (1 extra byte returned holding PEC) const uint8_t read_size = 2 + (_pec_supported ? 1 : 0); uint8_t buff[read_size]; // buffer to hold results // read the appropriate register from the device if (!_dev->read_registers(reg, buff, sizeof(buff))) { return false; } // check PEC if (_pec_supported) { const uint8_t pec = get_PEC(AP_BATTMONITOR_SMBUS_I2C_ADDR, reg, true, buff, 2); if (pec != buff[2]) { return false; } } // convert buffer to word data = (uint16_t)buff[1]<<8 | (uint16_t)buff[0]; // return success return true; } /// get_PEC - calculate packet error correction code of buffer uint8_t AP_BattMonitor_SMBus::get_PEC(const uint8_t i2c_addr, uint8_t cmd, bool reading, const uint8_t buff[], uint8_t len) const { // exit immediately if no data if (len == 0) { return 0; } // prepare temp buffer for calcing crc uint8_t tmp_buff[len+3]; tmp_buff[0] = i2c_addr << 1; tmp_buff[1] = cmd; tmp_buff[2] = tmp_buff[0] | (uint8_t)reading; memcpy(&tmp_buff[3],buff,len); // initialise crc to zero uint8_t crc = 0; uint8_t shift_reg = 0; bool do_invert; // for each byte in the stream for (uint8_t i=0; i