diff --git a/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.cpp b/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.cpp index a53b8ea8be..0578fae41f 100755 --- a/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.cpp +++ b/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.cpp @@ -15,12 +15,7 @@ extern const AP_HAL::HAL& hal; #define BATTMONITOR_SMBUS_MAXELL_SPECIFICATION_INFO 0x1a // specification info #define BATTMONITOR_SMBUS_MAXELL_MANUFACTURE_NAME 0x20 // manufacturer name -#define BATTMONITOR_SMBUS_10_PEC_NOT_SUPPORT 0x10 // Smart Battery Specification v1.0 -#define BATTMONITOR_SMBUS_11_PEC_NOT_SUPPORT 0x21 // Smart Battery Specification v1.1 without PEC support -#define BATTMONITOR_SMBUS_11_PEC_SUPPORT 0x31 // Smart Battery Specification v1.1 with PEC support - -// A Block Read or Write is allowed to transfer a maximum of 32 data bytes. -#define READ_BLOCK_MAXIMUM_TRANSFER 0x20 +#define SMBUS_READ_BLOCK_MAXIMUM_TRANSFER 0x20 // A Block Read or Write is allowed to transfer a maximum of 32 data bytes. #define SMBUS_PEC_POLYNOME 0x07 // Polynome for CRC generation @@ -64,9 +59,9 @@ void AP_BattMonitor_SMBus_Maxell::read() void AP_BattMonitor_SMBus_Maxell::timer() { - // _pec_confirmed set true after confirming if it support PEC - if (!_pec_confirmed) { - _pec_confirmed = get_pec_support(); + // check if PEC is supported + if (!check_pec_support()) { + return; } uint16_t data; @@ -106,7 +101,7 @@ bool AP_BattMonitor_SMBus_Maxell::read_word(uint8_t reg, uint16_t& data) const } // check PEC - if (_pec_support) { + if (_pec_supported) { const uint8_t pec = get_PEC(AP_BATTMONITOR_SMBUS_I2C_ADDR, reg, true, buff, 2); if (pec != buff[2]) { return false; @@ -131,7 +126,7 @@ uint8_t AP_BattMonitor_SMBus_Maxell::read_block(uint8_t reg, uint8_t* data, bool } // sanity check length returned by smbus - if (bufflen == 0 || bufflen > READ_BLOCK_MAXIMUM_TRANSFER) { + if (bufflen == 0 || bufflen > SMBUS_READ_BLOCK_MAXIMUM_TRANSFER) { return 0; } @@ -145,7 +140,7 @@ uint8_t AP_BattMonitor_SMBus_Maxell::read_block(uint8_t reg, uint8_t* data, bool } // check PEC - if (_pec_support) { + if (_pec_supported) { uint8_t pec = get_PEC(AP_BATTMONITOR_SMBUS_I2C_ADDR, reg, true, buff, bufflen+1); if (pec != buff[bufflen+1]) { return 0; @@ -164,44 +159,46 @@ uint8_t AP_BattMonitor_SMBus_Maxell::read_block(uint8_t reg, uint8_t* data, bool return bufflen; } -// get PEC support using the version value in SpecificationInfo -bool AP_BattMonitor_SMBus_Maxell::get_pec_support() +// check if PEC supported with the version value in SpecificationInfo() function +// returns true once PEC is confirmed as working or not working +bool AP_BattMonitor_SMBus_Maxell::check_pec_support() { - uint16_t data; - uint8_t buff[READ_BLOCK_MAXIMUM_TRANSFER + 1]; + // exit immediately if we have already confirmed pec support + if (_pec_confirmed) { + return true; + } // specification info + uint16_t data; if (!read_word(BATTMONITOR_SMBUS_MAXELL_SPECIFICATION_INFO, data)) { - _pec_support = false; return false; } - // determine _pec_support is false when SpecInfo indicates no PEC support - if (((data & 0xFF) == BATTMONITOR_SMBUS_10_PEC_NOT_SUPPORT) || ((data & 0xFF) == BATTMONITOR_SMBUS_11_PEC_NOT_SUPPORT)) { - _pec_support = false; - return true; - } else if ((data & 0xFF) != BATTMONITOR_SMBUS_11_PEC_SUPPORT) { - _pec_support = false; - return false; - } + // extract version + uint8_t version = (data & 0xF0) >> 4; - // At first, set true. In the second time, determine it. - // This confirm to get the correct value with PEC support - if (_pec_support) { + // version less than 0011b (i.e. 3) do not support PEC + if (version < 3) { + _pec_supported = false; + _pec_confirmed = true; return true; } - // manufacturer name + // check manufacturer name + uint8_t buff[SMBUS_READ_BLOCK_MAXIMUM_TRANSFER + 1]; if (read_block(BATTMONITOR_SMBUS_MAXELL_MANUFACTURE_NAME, buff, true)) { - // In Hitachi maxell battery, specification info is 0x31 (SBSv1.1 with PEC support) but PEC isn't support + // Hitachi maxell batteries do not support PEC if (strcmp((char*)buff, "Hitachi maxell") == 0) { - _pec_support = false; + _pec_supported = false; + _pec_confirmed = true; return true; } } - _pec_support = true; - return false; + // assume all other batteries support PEC + _pec_supported = true; + _pec_confirmed = true; + return true; } /// get_PEC - calculate packet error correction code of buffer diff --git a/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.h b/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.h index 23edcb9a7c..7894be1550 100755 --- a/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.h +++ b/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Maxell.h @@ -22,17 +22,13 @@ private: void timer(void); - bool _pec_support = false; - - // it sets true after check if PEC is used - bool _pec_confirmed = false; - // read word from register // returns true if read was successful, false if failed bool read_word(uint8_t reg, uint16_t& data) const; - // get PEC support with the version value in SpecificationInfo() function - bool get_pec_support(); + // check if PEC supported with the version value in SpecificationInfo() function + // returns true once PEC is confirmed as working or not working + bool check_pec_support(); // read_block - returns number of characters read if successful, zero if unsuccessful uint8_t read_block(uint8_t reg, uint8_t* data, bool append_zero) const; @@ -42,4 +38,6 @@ private: uint8_t get_PEC(const uint8_t i2c_addr, uint8_t cmd, bool reading, const uint8_t buff[], uint8_t len) const; AP_HAL::OwnPtr _dev; + uint8_t _pec_confirmed; // count of the number of times PEC has been confirmed as working + bool _pec_supported; // true if pec is supported };