Library to interface to the TI BQ27441, a fuel gauge monitor
Fork of battery-gauge-bq27441 by
Diff: TESTS/unit_tests/default/main.cpp
- Revision:
- 1:566163f17cde
- Child:
- 3:ebd56471d57c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TESTS/unit_tests/default/main.cpp Mon Apr 10 11:18:51 2017 +0100 @@ -0,0 +1,605 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "battery_gauge_bq27441.h" + +using namespace utest::v1; + +// ---------------------------------------------------------------- +// COMPILE-TIME MACROS +// ---------------------------------------------------------------- + +// Pick some sensible minimum and maximum numbers +#define MAX_TEMPERATURE_READING_C 80 +#define MIN_TEMPERATURE_READING_C -20 +#define MIN_VOLTAGE_READING_MV 0 +#define MAX_VOLTAGE_READING_MV 12000 // Bigger than a 3 cell LiPo +#define MAX_CURRENT_READING_MA 2000 +#define MIN_CURRENT_READING_MA -2000 +#define MIN_CAPACITY_READING_MAH 0 +#define MAX_CAPACITY_READING_MAH 30000 // A very big battery indeed + +#ifndef PIN_I2C_SDA +// Default for C030 board +#define PIN_I2C_SDA PC_9 +#endif + +#ifndef PIN_I2C_SDC +// Default for C030 board +#define PIN_I2C_SDC PA_8 +#endif + +// The maximum size of configuration block +// that we can handle in one go +#define MAX_CONFIG_BLOCK_SIZE 32 + +// ---------------------------------------------------------------- +// PRIVATE VARIABLES +// ---------------------------------------------------------------- + +#ifdef TARGET_UBLOX_C027 +#error GOT HERE +// This required only for UTM board +static DigitalOut gI2CPullUpBar(P1_1, 0); +#endif +// I2C interface +I2C * gpI2C = new I2C(PIN_I2C_SDA, PIN_I2C_SDC); + +// An empty array, so that we can check for emptiness +static const char zeroArray[MAX_CONFIG_BLOCK_SIZE] = {0}; + +// ---------------------------------------------------------------- +// PRIVATE FUNCTIONS +// ---------------------------------------------------------------- + +// Print a buffer as a nice hex string +static void printBytesAsHex(const char * pBuf, uint32_t size) +{ + uint32_t x; + + printf (" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); + for (x = 1; x <= size; x++, pBuf++) + { + if (x % 16 == 8) { + printf ("%02x ", *pBuf); + } else if (x % 16 == 0) { + printf ("%02x\n", *pBuf); + } else { + printf ("%02x-", *pBuf); + } + } + + if (x % 16 != 1) { + printf("\n"); + } +} + +// ---------------------------------------------------------------- +// TESTS +// ---------------------------------------------------------------- + +// Test that the BQ27441 battery gauge can be initialised +void test_init() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + + TEST_ASSERT_FALSE(pBatteryGauge->init(NULL)); + TEST_ASSERT(pBatteryGauge->init(gpI2C)); +} + +// Test that battery capacity monitoring can be performed +void test_monitor() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->enableGauge()); + + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + // Normal case + TEST_ASSERT(pBatteryGauge->enableGauge()); + // TODO do something to assess whether it's actually working + TEST_ASSERT(pBatteryGauge->disableGauge()); + + // Normal case, slow mode + TEST_ASSERT(pBatteryGauge->enableGauge(true)); + // TODO do something to assess whether it's actually working slowly + TEST_ASSERT(pBatteryGauge->disableGauge()); +} + +// Test that battery detection can be performed +// TODO: find a way to check that a battery is not detected correctly +void test_battery_detection() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->isBatteryDetected()); + + // Normal case + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->isBatteryDetected()); +} + +// Test that a temperature reading can be performed +void test_temperature() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + int32_t temperatureC = MIN_TEMPERATURE_READING_C - 1; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->getTemperature(&temperatureC)); + + // Normal case + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->getTemperature(&temperatureC)); + printf ("Temperature %d C.\n", temperatureC); + // Range check + TEST_ASSERT((temperatureC >= MIN_TEMPERATURE_READING_C) && (temperatureC <= MAX_TEMPERATURE_READING_C)); + + // The parameter is allowed to be NULL + TEST_ASSERT(pBatteryGauge->getTemperature(NULL)); +} + +// Test that a voltage reading can be performed +void test_voltage() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + int32_t voltageMV = MIN_VOLTAGE_READING_MV - 1; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->getVoltage(&voltageMV)); + + // Normal case + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->getVoltage(&voltageMV)); + printf ("Voltage %.3f V.\n", ((float) voltageMV) / 1000); + // Range check + TEST_ASSERT((voltageMV >= MIN_VOLTAGE_READING_MV) && (voltageMV <= MAX_VOLTAGE_READING_MV)); + + // The parameter is allowed to be NULL + TEST_ASSERT(pBatteryGauge->getVoltage(NULL)); +} + +// Test that a current reading can be performed +void test_current() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + int32_t currentMA = MIN_CURRENT_READING_MA - 1; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->getCurrent(¤tMA)); + + // Normal case + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->getCurrent(¤tMA)); + printf ("Current %.3f A.\n", ((float) currentMA) / 1000); + // Range check + TEST_ASSERT((currentMA >= MIN_CURRENT_READING_MA) && (currentMA <= MAX_CURRENT_READING_MA)); + + // The parameter is allowed to be NULL + TEST_ASSERT(pBatteryGauge->getCurrent(NULL)); +} + +// Test that a remaining capacity reading can be performed +void test_remaining_capacity() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + int32_t capacityMAh = MIN_CAPACITY_READING_MAH - 1; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->getRemainingCapacity(&capacityMAh)); + + // Normal case + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->getRemainingCapacity(&capacityMAh)); + printf ("Remaining capacity %.3f Ah.\n", ((float) capacityMAh) / 1000); + // Range check + TEST_ASSERT((capacityMAh >= MIN_CAPACITY_READING_MAH) && (capacityMAh <= MAX_CAPACITY_READING_MAH)); + + // The parameter is allowed to be NULL + TEST_ASSERT(pBatteryGauge->getRemainingCapacity(NULL)); +} + +// Test that a remaining percentage reading can be performed +void test_remaining_percentage() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + int32_t batteryPercent = 101; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->getRemainingPercentage(&batteryPercent)); + + // Normal case + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->getRemainingPercentage(&batteryPercent)); + printf ("Remaining percentage %d%%.\n", batteryPercent); + // Range check + TEST_ASSERT((batteryPercent >= 0) && (batteryPercent <= 100)); + + // The parameter is allowed to be NULL + TEST_ASSERT(pBatteryGauge->getRemainingPercentage(NULL)); +} + +// Test advanced functions to read the configuration of the chip +void test_advanced_config_1() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint8_t subClassId = 80; // IT Cfg + int32_t offset = 0; + int32_t length = MAX_CONFIG_BLOCK_SIZE - offset; + char data1[MAX_CONFIG_BLOCK_SIZE]; + uint32_t deadArea1 = 0xdeadbeef; + char data2[MAX_CONFIG_BLOCK_SIZE]; + uint32_t deadArea2 = 0xdeadbeef; + + // Initialise the battery gauge + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + + // Read IT Cfg (total length 79 bytes), starting from 0, into data1 + subClassId = 80; + memset(&(data1[0]), 0, sizeof (data1)); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset); + printBytesAsHex(&(data1[0]), length); + TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1); + + // Read it again, with an offset of 16 bytes, into data2 + offset = 16; + length = MAX_CONFIG_BLOCK_SIZE - 16; + memset(&(data2[0]), 0, sizeof (data2)); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data2[0]))); + printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset); + printBytesAsHex(&(data2[0]), length); + // The second 16 bytes of data1 and the first 16 bytes of data2 should match + TEST_ASSERT_EQUAL_UINT8_ARRAY(&(data1[16]), &(data2[0]), 16); + TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea2); + + // Read the next block of IT Cfg into data1 + offset = MAX_CONFIG_BLOCK_SIZE; + length = MAX_CONFIG_BLOCK_SIZE; + memset(&(data1[0]), 0, sizeof (data1)); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset); + printBytesAsHex(&(data1[0]), length); + TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1); + + // Read the only the first 16 bytes, from the same offset into IT Cfg, into data2 + length = 16; + memset(&(data2[0]), 0, sizeof (data2)); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data2[0]))); + printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset); + printBytesAsHex(&(data2[0]), length); + // The first 16 bytes of data1 and data2 should match + TEST_ASSERT_EQUAL_UINT8_ARRAY(&(data1[0]), &(data2[0]), length); + // The remainder of data2 should be zero + TEST_ASSERT_EQUAL_UINT8_ARRAY(&(zeroArray[0]), &(data2[length]), sizeof(data2) - length); + TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea2); +} + +// Test advanced functions to write configuration to the chip +void test_advanced_config_2() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint8_t subClassId = 80; // IT Cfg + int32_t offset = 0; + int32_t length = MAX_CONFIG_BLOCK_SIZE - offset; + char data1[MAX_CONFIG_BLOCK_SIZE]; + uint32_t deadArea1 = 0xdeadbeef; + char data2[MAX_CONFIG_BLOCK_SIZE]; + + // Initialise the battery gauge + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + + // Read Delta Voltage, two bytes at offset 39 in sub-class State, into data1 + subClassId = 82; + offset = 39; + length = 2; + memset(&(data1[0]), 0, sizeof (data1)); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset); + printBytesAsHex(&(data1[0]), length); + TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1); + + // Copy Delta Voltage, change the lower byte and then write it back + (data1[1])++; + printf ("Modified data block:\n"); + printBytesAsHex(&(data1[0]), length); + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0]))); + printf("%d bytes written to subClassID %d, offset %d:\n", length, subClassId, offset); + + // Read it back and check that the Delta Voltage really is the new value + subClassId = 82; + offset = 32; + length = 9; + memset(&(data2[0]), 0, sizeof (data2)); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data2[0]))); + printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset); + printBytesAsHex(&(data2[0]), length); + TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1); + TEST_ASSERT_EQUAL_UINT32 (data1[0], data2[7]); + TEST_ASSERT_EQUAL_UINT32 (data1[1], data2[8]); + + // Now put Delta Voltage back as it was + (data2[8])--; + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0]))); + printf("%d bytes written to subClassID %d, offset %d:\n", length, subClassId, offset); +} + +// Test fail cases of the advanced configuration functions +void test_advanced_config_3() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint8_t subClassId = 80; // IT Cfg + int32_t offset = 0; + int32_t length = MAX_CONFIG_BLOCK_SIZE - offset; + char data1[MAX_CONFIG_BLOCK_SIZE]; + + // All calls should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0]))); + TEST_ASSERT_FALSE(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + + // Initialise the battery gauge + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + + // Perform some reads of bad length/offset combinations + offset = 0; + length = 33; + TEST_ASSERT_FALSE(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + TEST_ASSERT_FALSE(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0]))); + offset = 1; + length = 32; + TEST_ASSERT_FALSE(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + TEST_ASSERT_FALSE(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0]))); + offset = 31; + length = 2; + TEST_ASSERT_FALSE(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + TEST_ASSERT_FALSE(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0]))); + offset = 32; + length = 33; + TEST_ASSERT_FALSE(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + TEST_ASSERT_FALSE(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0]))); +} + +// Send a control word to the BQ27441 battery gauge chip +void test_advanced_control() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint16_t controlWord = 0x0002; // get FW version + uint16_t response = 0; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->advancedSendControlWord(controlWord, &response)); + + // Initialise the battery gauge + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + + // Normal case + TEST_ASSERT(pBatteryGauge->advancedSendControlWord(controlWord, &response)); + // FW version must be 0x0109 + TEST_ASSERT_EQUAL_UINT16(0x0109, response); + + // The parameter is allowed to be null + TEST_ASSERT(pBatteryGauge->advancedSendControlWord(controlWord, NULL)); +} + +// Read using a standard command from the BQ27441 battery gauge chip +void test_advanced_get() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint8_t address = 0x02; // Temperature + uint16_t value = 0; + int32_t temperatureC = -1; + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->advancedGet(address, &value)); + + // Initialise the battery gauge + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + + // Normal case + TEST_ASSERT(pBatteryGauge->advancedGet(address, &value)); + // Get the temperature via the standard API command + TEST_ASSERT(pBatteryGauge->getTemperature(&temperatureC)); + // Convert the value returned into a temperature reading and compare + // it with the real answer, allowing a 1 degree tolerance in case + // it has changed between readings. + TEST_ASSERT_INT32_WITHIN (1, temperatureC, ((int32_t) value / 10) - 273); + + // The parameter is allowed to be null + TEST_ASSERT(pBatteryGauge->advancedGet(address, NULL)); +} + +// Test that the chip can be sealed and unsealed +void test_advanced_seal() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint8_t subClassId = 80; // IT Cfg + int32_t offset = 78; // Position of the "TermV valid t" item at offset 78 + int32_t length = 1; // Length of "TermV valid t" + char data1[MAX_CONFIG_BLOCK_SIZE]; + char data2[MAX_CONFIG_BLOCK_SIZE]; + char data3[MAX_CONFIG_BLOCK_SIZE]; + int32_t value; + + memset(&(data1[0]), 0, sizeof (data1)); + memset(&(data2[0]), 0, sizeof (data2)); + memset(&(data3[0]), 0, sizeof (data3)); + + // Make sure that the device is not sealed from a previous field test run + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->advancedUnseal()); + + delete pBatteryGauge; + pBatteryGauge = new BatteryGaugeBq27441(); + // Calls should fail if the battery gauge has not been initialised + printf ("Calling advancedIsSealed()...\n"); + TEST_ASSERT_FALSE(pBatteryGauge->advancedIsSealed()); + printf ("Calling advancedSeal()...\n"); + TEST_ASSERT_FALSE(pBatteryGauge->advancedSeal()); + printf ("Calling advancedUnseal()...\n"); + TEST_ASSERT_FALSE(pBatteryGauge->advancedUnseal()); + + // Normal case + printf ("Calling init()...\n"); + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + printf ("Calling advancedIsSealed()...\n"); + TEST_ASSERT_FALSE(pBatteryGauge->advancedIsSealed()); + // This call should pass + printf ("Calling advancedGetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId , offset, length, &(data1[0]))); + + // Now seal it + printf ("Calling advancedSeal()...\n"); + TEST_ASSERT(pBatteryGauge->advancedSeal()); + printf ("Calling advancedIsSealed()...\n"); + TEST_ASSERT(pBatteryGauge->advancedIsSealed()); + memcpy (&(data2[0]), &(data1[0]), sizeof (data2)); + // Try to increment the "TermV valid t" item + (data2[0])++; + // These calls should all be unaffected by sealing + printf ("Calling advancedSetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0]))); + printf ("Calling advancedGetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data3[0]))); + TEST_ASSERT(memcmp (&(data2[0]), &(data3[0]), sizeof (data2)) == 0); + // Put "TermV valid t" back as it was + (data2[0])--; + printf ("Calling advancedSetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0]))); + printf ("Calling enableGauge()...\n"); + TEST_ASSERT(pBatteryGauge->enableGauge()); + printf ("Calling isBatteryDetected()...\n"); + TEST_ASSERT(pBatteryGauge->isBatteryDetected()); + printf ("Calling getTemperature()...\n"); + TEST_ASSERT(pBatteryGauge->getTemperature(&value)); + printf ("Calling getVoltage()...\n"); + TEST_ASSERT(pBatteryGauge->getVoltage(&value)); + printf ("Calling getCurrent()...\n"); + TEST_ASSERT(pBatteryGauge->getCurrent(&value)); + printf ("Calling getRemainingCapacity()...\n"); + TEST_ASSERT(pBatteryGauge->getRemainingCapacity(&value)); + printf ("Calling getRemainingPercentage()...\n"); + TEST_ASSERT(pBatteryGauge->getRemainingPercentage(&value)); + printf ("Calling enableGauge(\"true\")...\n"); + TEST_ASSERT(pBatteryGauge->enableGauge(true)); + printf ("Calling disableGauge()...\n"); + TEST_ASSERT(pBatteryGauge->disableGauge()); + + // Now unseal it + printf ("Calling advancedUnseal()...\n"); + TEST_ASSERT(pBatteryGauge->advancedUnseal()); + printf ("Calling advancedIsSealed()...\n"); + TEST_ASSERT_FALSE(pBatteryGauge->advancedIsSealed()); + // These calls should all still work + // Try to increment the "TermV valid t" item + (data2[0])++; + printf ("Calling advancedSetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0]))); + printf ("Calling advancedGetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data3[0]))); + TEST_ASSERT(memcmp (&(data2[0]), &(data3[0]), sizeof (data2)) == 0); + // Put "TermV valid t" back as it was + (data2[0])--; + printf ("Calling advancedSetConfig()...\n"); + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0]))); + printf ("Calling enableGauge(\"true\")...\n"); + TEST_ASSERT(pBatteryGauge->enableGauge(true)); + printf ("Calling isBatteryDetected()...\n"); + TEST_ASSERT(pBatteryGauge->isBatteryDetected()); + printf ("Calling getTemperature()...\n"); + TEST_ASSERT(pBatteryGauge->getTemperature(&value)); + printf ("Calling getVoltage()...\n"); + TEST_ASSERT(pBatteryGauge->getVoltage(&value)); + printf ("Calling getCurrent()...\n"); + TEST_ASSERT(pBatteryGauge->getCurrent(&value)); + printf ("Calling getRemainingCapacity()...\n"); + TEST_ASSERT(pBatteryGauge->getRemainingCapacity(&value)); + printf ("Calling getRemainingPercentage()...\n"); + TEST_ASSERT(pBatteryGauge->getRemainingPercentage(&value)); + printf ("Calling disableGauge()...\n"); + TEST_ASSERT(pBatteryGauge->disableGauge()); + + // TODO: I had some tests in here to check that init() and + // advancedUnseal() behave when given the wrong seal code. + // However, as soon as the chip gets a wrong seal code it + // refuses to unseal again (I tried a 4 second delay but + // that didn't help). This needs investigating. +} + +// Reset the BQ27441 battery gauge chip at the outset +void test_advanced_reset() { + BatteryGaugeBq27441 * pBatteryGauge = new BatteryGaugeBq27441(); + uint8_t subClassId = 80; // IT Cfg + int32_t offset = 78; // Position of the "TermV valid t" item at offset 78 + int32_t length = 1; // Length of "TermV valid t" + char data1[MAX_CONFIG_BLOCK_SIZE]; + char data2[MAX_CONFIG_BLOCK_SIZE]; + char data3[MAX_CONFIG_BLOCK_SIZE]; + + memset(&(data1[0]), 0, sizeof (data1)); + memset(&(data2[0]), 0, sizeof (data2)); + memset(&(data3[0]), 0, sizeof (data3)); + + // Call should fail if the battery gauge has not been initialised + TEST_ASSERT_FALSE(pBatteryGauge->advancedReset()); + + TEST_ASSERT(pBatteryGauge->init(gpI2C)); + TEST_ASSERT(pBatteryGauge->advancedUnseal()); + + // Normal case + // Increment the "TermV valid t" item + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0]))); + memcpy (&(data2[0]), &(data1[0]), sizeof (data2)); + (data2[0])++; + TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0]))); + // Read it back to make sure it was set + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data3[0]))); + TEST_ASSERT(memcmp (&(data2[0]), &(data3[0]), sizeof (data2)) == 0); + + // Now reset the chip and check that the value is back to what it was before + TEST_ASSERT(pBatteryGauge->advancedReset()); + TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data3[0]))); + TEST_ASSERT(memcmp (&(data1[0]), &(data3[0]), sizeof (data1)) == 0); +} + +// ---------------------------------------------------------------- +// TEST ENVIRONMENT +// ---------------------------------------------------------------- + +// Setup the test environment +utest::v1::status_t test_setup(const size_t number_of_cases) { + // Setup Greentea, timeout is long enough to run these tests with + // DEBUG_BQ27441 defined + // Note: timeout is quite long as the chip has 4 second + // timeouts in quite a lot of cases. + GREENTEA_SETUP(480, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +// Test cases +Case cases[] = { + Case("Initialisation", test_init), + Case("Monitoring", test_monitor), + Case("Battery detection", test_battery_detection), + Case("Temperature read", test_temperature), + Case("Voltage read", test_voltage), + Case("Current read", test_current), + Case("Remaining capacity read", test_remaining_capacity), + Case("Remaining percentage read", test_remaining_percentage), + Case("Advanced config read", test_advanced_config_1), + Case("Advanced config write", test_advanced_config_2), + Case("Advanced config read/write fail cases", test_advanced_config_3), + Case("Advanced control", test_advanced_control), + Case("Advanced get", test_advanced_get), + Case("Advanced seal", test_advanced_seal), + Case("Advanced reset", test_advanced_reset) +}; + +Specification specification(test_setup, cases); + +// ---------------------------------------------------------------- +// MAIN +// ---------------------------------------------------------------- + +// Entry point into the tests +int main() { + bool success = false; + + if (gpI2C != NULL) { + success = !Harness::run(specification); + } else { + printf ("Unable to instantiate I2C interface.\n"); + } + + return success; +} + +// End Of File