This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ27441EVM-G1A: Battery Percentage increase/decrease abruptly

Part Number: BQ27441EVM-G1A


Hello,

I am working with BQ27441-G1A fuelguage using I2C interface with microcontroller. I successfully communicate with BQ27441-G1A using I2C and successfully read and write. For your reference i attached my code. As you can see in my code in Fualguage_initialize() function i am writting Battery capicity, opconfig, Design Energy, Terminate Voltage, Taper Rate to fuelguage. And all those parameters successfully written to fuelguage which i verified by reading those values. And in Fualguage_Parameter() function i am reading Battery Percentage, Current, Voltage, Design Capacity, Full Capacity, Available Capacity, Battery charging/discharging status. I also attached hardware schematic for your reference. In my code i continuously calling Fualguage_Parameter() after some delay(which is 7 - 8 sec).

I am facing isuue which i mentioned below:

================= First scenario ====================

1) Consider currently i not connected USB charger with my board and my code displays Battery Percentage = 54% it works fine.

2) Now i connect USB charging cable to my board now battery is charging and it works fine.

3) Now i press reset switch in controller(still USB charging cable is attached to board) now in UART display Battery Percentage = 75%.

-- So here Battery Percentage increased abruptly with more difference than last reading. So here i am getting 21% difference which is much more than expected.

================= Second scenario ====================

1) Consider USB charging cable is already connected with my board and my code displays Battery Percentage = 75% it works fine.

2) Now i remove USB charging cable from my board now battery is discharging and it works fine.

3) Now i press reset switch in controller now in UART display Battery Percentage = 55%.

-- So here Battery Percentage decreased abruptly with more difference than last reading. So here i am getting 20% difference which is much more than expected.

These issues i am facing only if i connect/removes USB charging cable and reset the microcontroller else it works fine.

So why i am getting these much difference in Battery Percentage?

Please help me so that i can solve this issue.

Any help in this will be appreciated.

Thank You

  Bhavin

===================================== Fuelguage Schematic ================================================

===================================== Battery Charger Schematic ================================================

======================================== main.c ================================================

#include <stdio.h>
#include "Fualguage.h"
extern volatile I2C_FUNC s_I2C1HandlerFn;
/*-----------------------------------------------------------------------------------------*/
/*  Fuelguage variables                                                                   */
/*-----------------------------------------------------------------------------------------*/
extern volatile I2C_FUNC s_I2C0HandlerFn;
extern volatile uint8_t address;
extern volatile uint8_t RW;
extern volatile uint8_t TxRxdata[50];
extern volatile uint8_t TxRxindex;
extern volatile uint8_t Read_Write_Bytes;
extern volatile uint8_t transfer_complete;
volatile uint8_t read_fg = 0;
volatile uint8_t Percentage_bat;
extern Battery Bat_Parameter;
void my_delay(void)
{
uint32_t i = 800000;
while(i--);
i = 800000;
while(i--);
i = 800000;
while(i--);
i = 800000;
while(i--);
i = 800000;
while(i--);
}
/*-----------------------------------------------------------------------------------------*/
/*  System initializing clk,module and pin-muxing ops                                      */
/*-----------------------------------------------------------------------------------------*/
void SYS_Init(void)
{
 SYS_UnlockReg();  /* Unlock protected registers */
 /* Init System Clock */
 CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC,CLK_HCLK_CLK_DIVIDER(1));
 CLK_DisablePLL();
 CLK->AHBCLK &= ~CLK_AHBCLK_DMA_EN; /* Disable CRC engine Clock */
 FMC_Close();
 CLK->PWRCTL |= CLK_PWRCTL_LIRC_EN_Msk; /* enable LIRC and no need to call HIRC, it is enable at startup */
 CLK_WaitClockReady(CLK_CLKSTATUS_HIRC_STB_Msk |CLK_CLKSTATUS_LIRC_STB_Msk ); /* Waiting for clock ready */
 SystemCoreClockUpdate();
 /* Select IP clock source */
 CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_UART_CLK_DIVIDER(1));
 CLK_SetModuleClock(I2C0_MODULE, 0, 0);
 /* Enable IP clock */
 CLK_EnableModuleClock(UART0_MODULE);
 CLK_EnableModuleClock(I2C0_MODULE);
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function (pin multiplexing)                                                              */
/*---------------------------------------------------------------------------------------------------------*/
 /* Set multi function pin for UART0 */
#ifdef REF_BORD /* for getting prints through ICE usb cable */
 SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB0_MFP_Msk | SYS_PB_L_MFP_PB1_MFP_Msk);
 SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB0_MFP_UART0_TX | SYS_PB_L_MFP_PB1_MFP_UART0_RX);
#else
 SYS->PB_H_MFP &= ~(SYS_PB_H_MFP_PB14_MFP_Msk | SYS_PB_H_MFP_PB13_MFP_Msk);
 SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB14_MFP_UART0_TX | SYS_PB_H_MFP_PB13_MFP_UART0_RX);
#endif
 /* Set multi function pin for I2C1 */
 SYS->PA_H_MFP = (SYS_PA_H_MFP_PA12_MFP_I2C0_SCL | SYS_PA_H_MFP_PA13_MFP_I2C0_SDA);
 
}
/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main (void)
{
SYS_Init();  /* Init System, IP clock and multi-function I/O */
UART_Open(UART0, 115200);  /* Init UART to 115200-8n1 for print message */
ADC_Init();
I2C0_Init(); /* Init I2C0 as Master */
s_I2C0HandlerFn = (I2C_FUNC)I2C_MasterTRx;  /*registeering i2c interrupt specific callback function */
Fualguage_initialize();
#ifdef _ENABLE_PRINTF_
        flg = flags();
        printf("\nBefore BAT_INSERT cmd send Flags : ");
        for(i=15;i>=0;i--)
            printf("%d",(flg>>i) & 1);
        printf("\n\r");
#endif
if (executeControlWord(BQ27441_CONTROL_BAT_INSERT))
{
CLK_SysTickDelay(10000);
#ifdef _ENABLE_PRINTF_
        flg = flags();
        printf("\nAfter BAT_INSERT cmd send Flags : ");
        for(i=15;i>=0;i--)
            printf("%d",(flg>>i) & 1);
        printf("\n\r");
#endif
while((flags() & 0x0008) == 0) //wait till BAT_DET bit set
CLK_SysTickDelay(20);
}
CLK_SysTickDelay(10000);
my_delay();
my_delay();
my_delay();
Fualguage_Parameter();
while(1)
{
my_delay();
my_delay();
my_delay();
Fualguage_Parameter();
}
}
======================================== Fuelguage.c ================================================
#include "Nano1X2Series.h"
#include "Fualguage.h"
#include "nuvt_vbel.h"
#define TRUE                       1
#define FALSE                      0
#define READ 1
#define WRITE 0
uint8_t bat_percentage;
Battery Bat_Parameter = {0};
uint8_t FG_Init = SET_BATTERY_CAPACITY,WriteExtended_Case = ENTER_CONFIG;
uint8_t newCsum = 0;
uint8_t _sealFlag = 0; // Global to identify that IC was previously sealed
uint8_t _userConfigControl = 0; // Global to identify that user has control over 
// entering/exiting config
/*-----------------------------------------------------------------------------------------*/
/*  Fuelguage variables                                                                   */
/*-----------------------------------------------------------------------------------------*/
extern volatile I2C_FUNC s_I2C0HandlerFn;
extern volatile uint8_t address;
extern volatile uint8_t RW;
extern volatile uint8_t TxRxdata[50];
extern volatile uint8_t TxRxindex;
extern volatile uint8_t Read_Write_Bytes;
extern volatile uint8_t transfer_complete;
/*****************************************************************************
************************** Initialization Functions *************************
*****************************************************************************/
/*
@func: begin(void)
@param : none
@return val: uint8_t
@descrition:
Read BQ27441_DEVICE_ID
*/
uint8_t begin(void)
{
    uint16_t deviceID = 0;
    deviceID = deviceType(); // Read deviceType from BQ27441
    
    if(deviceID == BQ27441_DEVICE_ID)
    {
        return TRUE; // If device ID is valid, return true
    }
    
    return FALSE; // Otherwise return false
}
/*
@func: setCapacity(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures the design capacity of the connected battery.
*/
uint8_t setCapacity(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB;        
return writeExtendedData(BQ27441_ID_STATE, CAPACITY_OFFSET, capacityData, 2);         
}
/*
@func: setDesign_Energy(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures the design Energy of the connected battery.
*/
uint8_t setDesign_Energy(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_STATE, DESIGN_ENERGY_OFFSET, capacityData, 2);            
}
/*
@func: setTerminate_Voltage(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures the Terminate Voltage of the connected battery.
*/
uint8_t setTerminate_Voltage(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_STATE, TERMINATE_VTG_OFFSET, capacityData, 2);            
}
/*
@func: setTaper_Rate(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures the Taper Rate of the connected battery.
*/
uint8_t setTaper_Rate(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_STATE, TAPERRATE_OFFSET, capacityData, 2);    
}
/*
@func: setTaper_Voltage(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures the Taper Voltage of the connected battery.
*/
uint8_t setTaper_Voltage(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_STATE, TAPER_VTG_OFFSET, capacityData, 2);    
}
/*
@func: setGPOUT(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures the BQ72441's GPOUT pin for interrupt
*/
uint8_t setGPOUT(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB;
return writeExtendedData(BQ27441_ID_REGISTERS, OPCONFIG_OFFSET, capacityData, 2);
}
/*
@func: Set_SOC1_Threshold(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures BQ72441's low battery's threshold percentage
*/
uint8_t Set_SOC1_Threshold(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_DISCHARGE, SOC1_OFFSET, capacityData, 1);    
}
/*
@func: Set_FcSet_Threshold(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures BQ72441's low battery's threshold percentage
*/
uint8_t Set_FcSet_Threshold(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_CHG_TERMINATION, FC_SET_OFFSET, capacityData, 1);    
}
/*
@func: Set_FcSet_Threshold(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures BQ72441's low battery's threshold percentage
*/
uint8_t Set_FcClear_Threshold(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_CHG_TERMINATION, FC_CLEAR_OFFSET, capacityData, 1);    
}
/*
@func: Clear_SOC1_Threshold(uint16_t capacity)
@param : uint16_t
@return val: uint8_t
@descrition:
Configures BQ72441's clear threshold percentage
*/
uint8_t Clear_SOC1_Threshold(uint16_t capacity)
{
// Write to STATE subclass (82) of BQ27441 extended memory.
// Offset 0x0A (10)
// Design capacity is a 2-byte piece of data - MSB first
uint8_t capMSB;
uint8_t capLSB;
uint8_t capacityData[2] = {0};    
capMSB = capacity >> 8;
capLSB = capacity & 0x00FF;     
capacityData[0] = capMSB;        
capacityData[1] = capLSB; 
return writeExtendedData(BQ27441_ID_DISCHARGE, SOC1_CLEAR_OFFSET, capacityData, 1);    
}
/*****************************************************************************
********************** Battery Characteristics Functions ********************
*****************************************************************************/
/*
@func: voltage(void)
@param : none
@return val: uint16_t
@descrition:
Reads and returns the battery voltage
*/
uint16_t voltage(void)
{
return readWord(BQ27441_COMMAND_VOLTAGE);
}
/*
@func: current(current_measure type)
@param : current_measure
@return val: int16_t
@descrition:
Reads and returns the specified current measurement
*/
int16_t current(current_measure type)
{
int16_t current = 0;
switch (type)
{
        case AVG:
current = (int16_t) readWord(BQ27441_COMMAND_AVG_CURRENT);
break;
        case STBY:
current = (int16_t) readWord(BQ27441_COMMAND_STDBY_CURRENT);
break;
        case MAX:
current = (int16_t) readWord(BQ27441_COMMAND_MAX_CURRENT);
break;
}
return current;
}
/*
@func: capacity(capacity_measure type)
@param : capacity_measure
@return val: uint16_t
@descrition:
Reads and returns the specified capacity measurement
*/
uint16_t capacity(capacity_measure type)
{
uint16_t capacity = 0;
switch (type)
{
        case REMAIN:
return readWord(BQ27441_COMMAND_REM_CAPACITY);
break;
        case FULL:
return readWord(BQ27441_COMMAND_FULL_CAPACITY);
break;
        case AVAIL:
capacity = readWord(BQ27441_COMMAND_NOM_CAPACITY);
break;
        case AVAIL_FULL:
capacity = readWord(BQ27441_COMMAND_AVAIL_CAPACITY);
break;
        case REMAIN_F: 
capacity = readWord(BQ27441_COMMAND_REM_CAP_FIL);
break;
        case REMAIN_UF:
capacity = readWord(BQ27441_COMMAND_REM_CAP_UNFL);
break;
        case FULL_F:
capacity = readWord(BQ27441_COMMAND_FULL_CAP_FIL);
break;
        case FULL_UF:
capacity = readWord(BQ27441_COMMAND_FULL_CAP_UNFL);
break;
        case DESIGN:
capacity = readWord(BQ27441_EXTENDED_CAPACITY);
}
return capacity;
}
/*
@func: power(void)
@param : none
@return val: int16_t
@descrition:
Reads and returns measured average power
*/
int16_t power(void)
{
return (int16_t) readWord(BQ27441_COMMAND_AVG_POWER);
}
/*
@func: soc(soc_measure type)
@param : soc_measure
@return val: uint16_t
@descrition:
Reads and returns specified state of charge measurement
*/
uint16_t soc(soc_measure type)
{
uint16_t socRet = 0;
switch (type)
{
        case FILTERED:
socRet = readWord(BQ27441_COMMAND_SOC);
break;
        case UNFILTERED:
socRet = readWord(BQ27441_COMMAND_SOC_UNFL);
break;
}
return socRet;
}
/*
@func: soh(soh_measure type)
@param : soh_measure
@return val: uint8_t(State of health)
@descrition:
Reads and returns specified state of health measurement
*/
uint8_t soh(soh_measure type)
{
uint16_t sohRaw;
uint8_t sohStatus;
uint8_t sohPercent;
sohRaw = readWord(BQ27441_COMMAND_SOH);
sohStatus = sohRaw >> 8;
sohPercent = sohRaw & 0x00FF;
if (type == PERCENT)
return sohPercent;
else
return sohStatus;
}
/*
@func: temperature(temp_measure type)
@param : temp_measure
@return val: uint16_t(temperature measurement)
@descrition:
Reads and returns specified temperature measurement
*/
uint16_t temperature(temp_measure type)
{
uint16_t temp = 0;
switch (type)
{
        case BATTERY:
temp = readWord(BQ27441_COMMAND_TEMP);
break;
        case INTERNAL_TEMP:
temp = readWord(BQ27441_COMMAND_INT_TEMP);
break;
}
return temp;
}
/*****************************************************************************
*************************** Control Sub-Commands ****************************
*****************************************************************************/
/*
@func: deviceType(void)
@param : none
@return val: uint16_t(device type)
@descrition:
Read the device type - should be 0x0421
*/
uint16_t deviceType(void)
{
return readControlWord(BQ27441_CONTROL_DEVICE_TYPE);
}
/*
@func: enterConfig(uint8_t)
@param : uint8_t(userControl)
@return val: uint8_t
@descrition:
-- if seal then unseal
-- Enter configuration mode - Set CFGUPMODE bit in Flags()
*/
uint8_t enterConfig(uint8_t userControl)
{
int i = 0;
if (userControl) _userConfigControl = TRUE;
if (sealed())
{
#ifdef _ENABLE_PRINTF_                
        uint16_t stat = status();
        printf("\n\rBefore Unsealed Control_STATUS :");
        for(i=0x0F; i >= 0; i--)
        {
            printf("%d",(stat >> i) & 1);
        }
#endif        
        
unseal(); // Must be unsealed before making changes
        while(status() & 0x2000)
            CLK_SysTickDelay(8000);
#ifdef _ENABLE_PRINTF_                
        stat = status();
        printf("\n\rAfter Unsealed Control_STATUS :");
        for(i=0x0F; i >= 0; i--)
        {
            printf("%d",(stat >> i) & 1);
        }
#endif             
}
if (executeControlWord(BQ27441_CONTROL_SET_CFGUPDATE))
{                
uint16_t timeout = BQ72441_I2C_TIMEOUT;  
uint16_t j = 0;
while ((timeout--) && (!(flags() & BQ27441_FLAG_CFGUPMODE)))
CLK_SysTickDelay(10000);
if (timeout > 0)
        {
return TRUE;
        }
}
return FALSE;
}
/*
@func: exitConfig(uint8_t)
@param : uint8_t(resim)
@return val: uint8_t(TRUE or FALSE)
@descrition:
-- Exit configuration mode with the option to perform a resimulation
-- There are two methods for exiting config mode:
1. Execute the EXIT_CFGUPDATE command
2. Execute the SOFT_RESET command
-- EXIT_CFGUPDATE exits config mode _without_ an OCV (open-circuit voltage)
-- measurement, and without resimulating to update unfiltered-SoC and SoC.
-- If a new OCV measurement or resimulation is desired, SOFT_RESET or
-- EXIT_RESIM should be used to exit config mode.
*/
uint8_t exitConfig(uint8_t resim)
{
if (resim)
{        
if (softReset())
{    
uint16_t j = 0;
            CLK_SysTickDelay(10000);
while (flags() & BQ27441_FLAG_CFGUPMODE)
CLK_SysTickDelay(10000);
            
            if(FG_Init == SET_SOC1_CLEAR_THRESHOLD)
            {
                seal(); // Seal back up if we IC was sealed coming in
                while(!(status() & 0x2000))
                    CLK_SysTickDelay(10000);
            }
            return TRUE;      
}        
return FALSE;        
}
else
{
return executeControlWord(BQ27441_CONTROL_EXIT_CFGUPDATE);        
}
}
/*
@func: flags(void)
@param : none
@return val: uint16_t
@descrition:
-- Read the flags() command
*/
uint16_t flags(void)
{
return readWord(BQ27441_COMMAND_FLAGS);
}
/*
@func: status(void)
@param : none
@return val: uint16_t
@descrition:
-- Read the CONTROL_STATUS subcommand of control()
*/
uint16_t status(void)
{
return readControlWord(BQ27441_CONTROL_STATUS);
}
/*
@func: sealed(void)
@param : none
@return val: uint8_t
@descrition:
-- Check if the BQ27441-G1A is sealed or not.
*/
uint8_t sealed(void)
{
uint16_t stat = status();
int i = 0;
#ifdef _ENABLE_PRINTF_    
    printf("\n\rin sealed Control_STATUS :");
    for(i=0x0F; i >= 0; i--)
    {
        printf("%d",(stat >> i) & 1);
    }
    printf("\n\r");
#endif    
return ((stat >> 13) & 1);
}
/*
@func: seal(void)
@param : none
@return val: uint8_t
@descrition:
-- Seal the BQ27441-G1A
*/
uint8_t seal(void)
{    
return readControlWord(BQ27441_CONTROL_SEALED);
}
/*
@func: unseal(void)
@param : none
@return val: uint8_t
@descrition:
-- unseal the BQ27441-G1A
*/
uint8_t unseal(void)
{
// To unseal the BQ27441, write the key to the control
// command. Then immediately write the same key to control again.
if (readControlWord(BQ27441_UNSEAL_KEY))
{
return readControlWord(BQ27441_UNSEAL_KEY);
}
return FALSE;
}
/*
@func: opConfig(void)
@param : none
@return val: uint16_t
@descrition:
-- Read the 16-bit register from extended data
*/
uint16_t opConfig(void)
{
return readWord(BQ27441_EXTENDED_OPCONFIG);
}
/*
@func: softReset(void)
@param : none
@return val: uint8_t
@descrition:
-- Issue a soft-reset to the BQ27441-G1A
*/
uint8_t softReset(void)
{
return executeControlWord(BQ27441_CONTROL_SOFT_RESET);
}
/*
@func: readWord(uint16_t subAddress)
@param : uint16_t(subAddress)
@return val: uint16_t
@descrition:
-- Read a 16-bit command word from the BQ27441-G1A
*/
uint16_t readWord(uint16_t subAddress)
{
uint8_t data[2];    
//    HAL_I2C_Mem_Read(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,subAddress,1,(unsigned char *)data,2,100);
FG_I2C_Read(subAddress,2);
  return ((uint16_t) TxRxdata[1] << 8) | TxRxdata[0];
}
/*
@func: readControlWord(uint16_t function)
@param : uint16_t(function)
@return val: uint16_t
@descrition:
-- Read a 16-bit subcommand() from the BQ27441-G1A's control()
*/
uint16_t readControlWord(uint16_t function)
{
uint8_t subCommandMSB;
uint8_t subCommandLSB;
uint8_t command[2] = {0};
uint8_t data[2] = {0, 0};
subCommandMSB = (function >> 8);
subCommandLSB = (function & 0x00FF);
command[0] = subCommandLSB;
command[1] = subCommandMSB;
FG_I2C_Write(0,2,command);
// HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,(uint8_t) 0,1,command,2,100);
        
    CLK_SysTickDelay(7);    
FG_I2C_Read(0,2);
if(transfer_complete == 1)
{
//    if(!(HAL_I2C_Mem_Read(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,(uint8_t)0,1,(unsigned char *)data,2,100)))
return ((uint16_t)TxRxdata[1] << 8) | TxRxdata[0];
}
return FALSE;
}
/*
@func: executeControlWord(uint16_t function)
@param : uint16_t(function)
@return val: uint8_t
@descrition:
-- Execute a subcommand() from the BQ27441-G1A's control()
*/
uint8_t executeControlWord(uint16_t function)
{
uint8_t subCommandMSB;
uint8_t subCommandLSB;
uint8_t command[2] = {0};
uint8_t data[2] = {0, 0};
subCommandMSB = (function >> 8);
subCommandLSB = (function & 0x00FF);
command[0] = subCommandLSB;
command[1] = subCommandMSB;
FG_I2C_Write(0,2,command);
if(transfer_complete == 1)
// if(!(HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,(uint8_t) 0,1,command,2,100)))
    {
return TRUE;
    }
return FALSE;
}
/*****************************************************************************
************************** Extended Data Commands ***************************
*****************************************************************************/
/*
@func: blockDataControl(void)
@param : none
@return val: uint8_t
@descrition:
-- Issue a BlockDataControl() command to enable BlockData access
*/
uint8_t blockDataControl(void)
{
uint8_t enableByte = 0x00;
FG_I2C_Write(BQ27441_EXTENDED_CONTROL,1,&enableByte);
//    return (!(HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,BQ27441_EXTENDED_CONTROL,1,&enableByte,1,100)));
if(transfer_complete == 1)
{
return TRUE;
}
return FALSE;
}
/*
@func: blockDataClass(uint8_t id)
@param : uint8_t
@return val: uint8_t
@descrition:
-- Issue a DataClass() command to set the data class to be accessed
*/
uint8_t blockDataClass(uint8_t id)
{
FG_I2C_Write(BQ27441_EXTENDED_DATACLASS,1,&id);
//    return (!(HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,BQ27441_EXTENDED_DATACLASS,1,&id,1,100)));
if(transfer_complete == 1)
{
return TRUE;
}
return FALSE;   
}
/*
@func: blockDataOffset(uint8_t offset)
@param : uint8_t
@return val: uint8_t
@descrition:
-- Issue a DataBlock() command to set the data block to be accessed
*/
uint8_t blockDataOffset(uint8_t offset)
{
FG_I2C_Write(BQ27441_EXTENDED_DATABLOCK,1,&offset);
//    return (!(HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,BQ27441_EXTENDED_DATABLOCK,1,&offset,1,100)));
if(transfer_complete == 1)
{
return TRUE;
}
return FALSE;     
}
/*
@func: blockDataChecksum(void)
@param : none
@return val: uint8_t
@descrition:
-- Read the current checksum using BlockDataCheckSum()
*/
uint8_t blockDataChecksum(void)
{
uint8_t csum;
FG_I2C_Read(BQ27441_EXTENDED_CHECKSUM,1);
//    HAL_I2C_Mem_Read(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,BQ27441_EXTENDED_CHECKSUM,1,&csum,1,100);
csum = TxRxdata[0];
return csum;
}
/*
@func: readBlockData(uint8_t offset)
@param : uint8_t
@return val: uint8_t
@descrition:
-- Use BlockData() to read a byte from the loaded extended data
*/
uint8_t readBlockData(uint8_t offset)
{
uint8_t ret;
uint8_t address = offset + BQ27441_EXTENDED_BLOCKDATA;
FG_I2C_Read(address,1);
//    HAL_I2C_Mem_Read(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,address,1,&ret,1,100);
ret = TxRxdata[0];    
return ret;
}
/*
@func: my_readBlockData(uint8_t offset)
@param : uint8_t
@return val: uint8_t
@descrition:
-- Use BlockData() to read a byte from the loaded extended data
*/
uint16_t my_readBlockData(uint8_t offset)
{
uint8_t ret[2] = {0};
uint8_t address = offset + BQ27441_EXTENDED_BLOCKDATA;
FG_I2C_Read(address,2);
//    HAL_I2C_Mem_Read(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,address,1,ret,2,100);
    return ((TxRxdata[0] << 8) | TxRxdata[1]);
}
/*
@func: writeBlockData(uint8_t offset, uint8_t data)
@param : uint8_t,uint8_t
@return val: uint8_t
@descrition:
-- Use BlockData() to write a byte to an offset of the loaded data
*/
uint8_t writeBlockData(uint8_t offset, uint8_t data)
{
uint8_t address = offset + BQ27441_EXTENDED_BLOCKDATA; 
FG_I2C_Write(address,1,&data);
//    return (!(HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,address,1,&data,1,100)));
if(transfer_complete == 1)
{
return TRUE;
}
return FALSE;    
}
/*
@func: computeBlockChecksum(void)
@param : none
@return val: uint8_t
@descrition:
-- Read all 32 bytes of the loaded extended data and compute a 
checksum based on the values.
*/
uint8_t computeBlockChecksum(void)
{
uint8_t data[32] = {0};    
uint8_t csum = 0;
int i=0;
FG_I2C_Read(BQ27441_EXTENDED_BLOCKDATA,32);
//    HAL_I2C_Mem_Read(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,BQ27441_EXTENDED_BLOCKDATA,1,data,32,100);
   
   
for (i=0; i<32; i++)
{
csum += TxRxdata[i];
}
csum = 255 - csum;
#ifdef _ENABLE_PRINTF_    
    printf("\r\ncsum :%d\r\n",csum);
#endif    
return csum;
}
/*
@func: writeBlockChecksum(uint8_t csum)
@param : uint8_t
@return val: uint8_t
@descrition:
-- Use the BlockDataCheckSum() command to write a checksum value
*/
uint8_t writeBlockChecksum(uint8_t csum)
{
FG_I2C_Write(BQ27441_EXTENDED_CHECKSUM,1,&csum);
//    return (!(HAL_I2C_Mem_Write(&Fualguage_I2C2descriptor,BQ27741_I2C_ADDRESS,BQ27441_EXTENDED_CHECKSUM,1,&csum,1,100)));
if(transfer_complete == 1)
{
return TRUE;
}
    return FALSE;
}
/*
@func: readExtendedData(uint8_t classID, uint8_t offset)
@param : uint8_t,uint8_t
@return val: uint16_t
@descrition:
-- Read from extended data specifying a class ID and position offset
*/
uint16_t readExtendedData(uint8_t classID, uint8_t offset)
{
uint16_t retData = 0;
uint8_t oldCsum = 0;
if (!_userConfigControl) enterConfig(FALSE);
    
if (!blockDataControl()) // // enable block data memory control
return FALSE; // Return false if enable fails
    CLK_SysTickDelay(200000);
if (!blockDataClass(classID)) // Write class ID using DataBlockClass()
return FALSE;
    CLK_SysTickDelay(200000);
blockDataOffset(offset / 32); // Write 32-bit block offset (usually 0)
    CLK_SysTickDelay(200000);
computeBlockChecksum(); // Compute checksum going in
    CLK_SysTickDelay(200000);
oldCsum = blockDataChecksum();
    // retData = readBlockData(offset % 32); // Read from offset (limit to 0-31)
    retData = my_readBlockData(offset % 32); // Read from offset (limit to 0-31)
    if (!_userConfigControl) exitConfig(TRUE);
    CLK_SysTickDelay(200000);
    
return retData;
}
/*
@func: writeExtendedData
@param : uint8_t,uint8_t,uint8_t *,uint8_t
@return val: uint8_t
@descrition:
-- Write a specified number of bytes to extended data specifying a 
class ID, position offset.
*/
uint8_t writeExtendedData(uint8_t classID, uint8_t offset, uint8_t * data, uint8_t len)
{
// while(WriteExtended_Case <= EXIT_CONFIG)
// {
    switch(WriteExtended_Case)
    {
        case ENTER_CONFIG :
        {          
            if (len > 32)
                return FALSE;
            
            if (!_userConfigControl) enterConfig(FALSE);
            
            if (!blockDataControl()) // // enable block data memory control
                return FALSE; // Return false if enable fails
//            CLK_SysTickDelay(7);
CLK_SysTickDelay(10000);
            if (!blockDataClass(classID)) // Write class ID using DataBlockClass()
                return FALSE;
            
//            CLK_SysTickDelay(7);
CLK_SysTickDelay(10000);
            blockDataOffset(offset / 32); // Write 32-bit block offset (usually 0)             
            WriteExtended_Case = COMPUTE_BLOCK_CHKSUM;
        }
        break;
        
        case COMPUTE_BLOCK_CHKSUM :
        {
            computeBlockChecksum(); // Compute checksum going in            
            WriteExtended_Case = GET_CHECKSUM;
        }
        break;
        
        case GET_CHECKSUM :
        {
int i = 0;
            uint8_t oldCsum = blockDataChecksum();
#ifdef _ENABLE_PRINTF_                                
            printf("\n\roldCsum :%u\n\r",oldCsum);
#endif                    
            // Write data bytes:
            for (i = 0; i < len; i++)
            {
                // Write to offset, mod 32 if offset is greater than 32
                // The blockDataOffset above sets the 32-bit block
                writeBlockData((offset % 32) + i, data[i]); 
//                CLK_SysTickDelay(7);
CLK_SysTickDelay(10000);
            }
        
            // Write new checksum using BlockDataChecksum (0x60)
            newCsum = computeBlockChecksum(); // Compute the new checksum
#ifdef _ENABLE_PRINTF_                
            printf("\n\rnewCsum :%u\n\r",newCsum);
#endif                
            WriteExtended_Case = WRITE_CHECKSUM;
        }
        break;
        
        case WRITE_CHECKSUM:
        {
            writeBlockChecksum(newCsum);                
            if(SOC1_CLR_THRESHOLD || DEDIGN_CAPACITY)
            {                
                WriteExtended_Case = EXIT_CONFIG;
            }
            else
            {
                WriteExtended_Case = ENTER_CONFIG;
                return TRUE;
            }
        }
        break;
        
        case EXIT_CONFIG :
        {                
            exitConfig(TRUE);                            
// WriteExtended_Case++;
            WriteExtended_Case = ENTER_CONFIG;
            return TRUE;
        }
        break;
    } //Switch
   
    return FALSE;
}
/*
@func: read_battery_percentage(void)
@param : none
@return val: none
@descrition:
-- read battery percentage
*/
void read_battery_percentage(void)
{
    do
    {
        Bat_Parameter.Percentage = soc(FILTERED);
        if(Bat_Parameter.Percentage <= 100)
            break;
    }while(Bat_Parameter.Percentage > 100);
    
    bat_percentage =((Bat_Parameter.Percentage*100)/833);
    
#ifdef _ENABLE_PRINTF_                 
    printf("Percentage : %u %\n\r",Bat_Parameter.Percentage);
#endif        
    
}
/*
@func: Fualguage_initialize(void)
@param : none
@return val: none
@descrition:
-- Fualguage Initialization set Design Capacity,Design Energy,
Terminate Voltage and Taper Rate
*/
void Fualguage_initialize(void)
{
    
//    uint16_t data = opConfig();
    
    while(FG_Init <= SET_SOC1_CLEAR_THRESHOLD)
    {
        switch(FG_Init)
        {
            case SET_BATTERY_CAPACITY :
            {
#ifdef _ENABLE_PRINTF_           
                printf("\n\r-------------------in Set Design Capacity...\n\r\n\r");                
#endif
                if(setCapacity(BATTERY_CAPACITY))
                {
                    FG_Init = SET_OPCONFIG;
                }
            }
            break;
            
            case SET_OPCONFIG :
            {
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set GPOUT Pin Config...\n\r\n\r");
#endif            
                if(setGPOUT(OPCONFIG))
                    FG_Init = SET_DESIGN_ENERGY;
            }
            break;
            
            case SET_DESIGN_ENERGY :
            {
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set Design Energy...\n\r\n\r");
#endif    
                if(setDesign_Energy(DESIGN_ENERGY))
{
                    FG_Init = SET_TERMINATE_VOLTAGE;
// FG_Init = SET_FC_SET;
/* exitConfig(TRUE);
FG_Init++; */
}
            }
            break;
            
            case SET_TERMINATE_VOLTAGE :
            {           
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set Terminate Voltage...\n\r\n\r");
#endif    
                if(setTerminate_Voltage(TERMINATE_VOLTAGE))
                    FG_Init = SET_TAPER_RATE;
            }
            break;
            
            case SET_TAPER_RATE :
            {                
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set Taper Rate...\n\r\n\r");
#endif    
                if(setTaper_Rate(TAPER_RATE))
{
                    FG_Init = SET_TAPER_VOLTAGE;
FG_Init = SET_SOC1_CLEAR_THRESHOLD;
exitConfig(TRUE);
FG_Init++;
}
            }
            break;
            
            case SET_TAPER_VOLTAGE :
            {    
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set Taper Voltage...\n\r\n\r");
#endif        
                if(setTaper_Voltage(TAPER_VOLTAGE))
                    FG_Init = SET_SOC1_THRESHOLD;
            }
            break;
            
            case SET_SOC1_THRESHOLD :
            {
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set SOC1 Set Threshold...\n\r\n\r");
#endif            
                if(Set_SOC1_Threshold(SOC1_SET_THRESHOLD))
                    FG_Init = SET_FC_SET;
            }
            break;
            
            
            case SET_FC_SET :
            {
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set FC_SET Threshold...\n\r\n\r");
#endif            
                if(Set_FcSet_Threshold(FC_SET))
                    FG_Init = SET_FC_CLEAR;
            }
            break;          
            
            case SET_FC_CLEAR :
            {
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set FC_CLEAR Threshold...\n\r\n\r");
#endif            
                if(Set_FcClear_Threshold(FC_CLEAR))
{                    
FG_Init = SET_SOC1_CLEAR_THRESHOLD;
exitConfig(TRUE);
FG_Init++;
}
            }
            break;                                  
            
            case SET_SOC1_CLEAR_THRESHOLD :
            {
#ifdef _ENABLE_PRINTF_             
                printf("\n\r-------------------in Set SOC1 Clear Threshold...\n\r\n\r");
#endif                
                if(Clear_SOC1_Threshold(SOC1_CLEAR_THRESHOLD))
                    FG_Init++;
            }
            break;
            
        } //Switch          
        
    }
    
//    CLK_SysTickDelay(900);       
//    CLK_SysTickDelay(50000);
}
void Check_Battery_Chg_Dischg(void)
{
    int Avg_Power = 0;
    Avg_Power = power();
    
    /* Discharging */
    if(Avg_Power < 0)
    {
        Bat_Parameter.discharge = 1;
        Bat_Parameter.charging = 0;
#ifdef _ENABLE_PRINTF_                 
        printf("Battery is Discharging\n");
#endif       
    }
    /* Charging */
    else if(Avg_Power > 0)
    {
        Bat_Parameter.charging = 1;
        Bat_Parameter.discharge = 0;
#ifdef _ENABLE_PRINTF_                 
        printf("Battery is Charging\n");
#endif        
    }   
    /* Not Discharging */
    else if(Avg_Power == 0)
    {
        Bat_Parameter.charging = 0;
        Bat_Parameter.discharge = 0;
#ifdef _ENABLE_PRINTF_                 
        printf("Battery is not Charging and not Discharging\n");
#endif        
    }      
    
}
/*
@func: Fualguage_Parameter(void)
@param : none
@return val: none
@descrition:
read Fualguage parameters
- Battery Percentage
- Battery Current
- Battery Voltage
- Fualguage Design Capacity
- Fualguage Full Capacity
- Fualguage Available Capacity
*/
void Fualguage_Parameter(void)
{
//    if(FG_INITIALIZATION_COMPLETE)
//    {
        uint16_t flg = 0,opcnfg = 0,Battery_Voltage = 0;
int8_t i = 0;
uint16_t stat = 0;
        
        do
        {
            Bat_Parameter.Percentage = soc(FILTERED);
            if(Bat_Parameter.Percentage <= 100)
                break;
        }while(Bat_Parameter.Percentage > 100);
//#if 0 
//        sec = 0;
//        while(sec<3);
//        bat_percentage =((Bat_Parameter.Percentage*100)/833);
        
        
#ifdef _ENABLE_PRINTF_                 
        printf("Percentage : %u %\n\r",Bat_Parameter.Percentage);
#endif    
        
        Bat_Parameter.Current = current(AVG);
        if(Bat_Parameter.Current < 0)
            Bat_Parameter.Current = -(Bat_Parameter.Current);
#ifdef _ENABLE_PRINTF_                 
        printf("Current : %d mAh\n\r",Bat_Parameter.Current);
#endif    
        
//        sec = 0;
//        while(sec<3);        
        
        Battery_Voltage = voltage();
        Bat_Parameter.Voltage = (float)Battery_Voltage/1000;
#ifdef _ENABLE_PRINTF_                 
        printf("Voltage : %f V\n\r",Bat_Parameter.Voltage);
#endif    
        
//        sec = 0;
//        while(sec<3);        
        
        Bat_Parameter.Design_Capacity = capacity(DESIGN);
#ifdef _ENABLE_PRINTF_                 
        printf("DESIGN Capacity : %u mAh\n\r",Bat_Parameter.Design_Capacity);
#endif    
        
//        sec = 0;
//        while(sec<3);        
        
        Bat_Parameter.Full_Capacity = capacity(FULL);
#ifdef _ENABLE_PRINTF_                 
        printf("FULL Capacity : %u mAh\n\r",Bat_Parameter.Full_Capacity);
#endif    
        
//        sec = 0;
//        while(sec<3);        
        
        Bat_Parameter.Avail_Capacity = capacity(AVAIL);
#ifdef _ENABLE_PRINTF_                 
        printf("AVAIL Capacity : %u mAh\n\r",Bat_Parameter.Avail_Capacity);
#endif    
        
        
//        sec = 0;
//        while(sec<3);        
        
#ifdef _ENABLE_PRINTF_
        flg = flags();
        printf("\nFlags : ");
        for(i=15;i>=0;i--)
            printf("%d",(flg>>i) & 1);
        printf("\n\r");
#endif                
        
        
//        sec = 0;
//        while(sec<3);        
        
#ifdef _ENABLE_PRINTF_    
        stat = status();
        printf("\n\rControl_STATUS :");
        for(i=0x0F; i >= 0; i--)
        {
            printf("%d",(stat >> i) & 1);
        }
        printf("\n\r");
#endif 
        
//        sec = 0;
//        while(sec<3);        
        
#ifdef _ENABLE_PRINTF_   
        opcnfg = opConfig();        
        printf("\nOpConfig : ");
        for(i=15;i>=0;i--)
            printf("%d",(opcnfg>>i) & 1);
        printf("\n\r");
#endif 
        
//        sec = 0;
//        while(sec<3);        
        
        Check_Battery_Chg_Dischg();
 //#endif   
//    }
}
void FG_I2C_Read(uint8_t Address,uint8_t read_bytes)
{
memset(TxRxdata,0,sizeof(TxRxdata));
TxRxindex = 0;
transfer_complete = 0;
Read_Write_Bytes = read_bytes;
address = Address;
RW = READ;
/* I2C as master sends START signal */
  I2C_SET_CONTROL_REG(I2C0, I2C_STA);
while(transfer_complete == 0);
}
void FG_I2C_Write(uint8_t Address,uint8_t write_bytes,uint8_t *data)
{
uint8_t i = 0;
memset(TxRxdata,0,sizeof(TxRxdata));
for(i=0;i < write_bytes;i++)
TxRxdata[i] = data[i];
TxRxindex = 0;
transfer_complete = 0;
Read_Write_Bytes = write_bytes;
address = Address;
RW = WRITE;
/* I2C as master sends START signal */
  I2C_SET_CONTROL_REG(I2C0, I2C_STA);
while(transfer_complete == 0);
}
======================================== Fuelguage.h ================================================

#ifndef __FUALGUAGE_H
#define __FUALGUAGE_H

#define TIMEOUT 10000
#define BQ72441_I2C_TIMEOUT 2000

//----------------------- Battery parameters macros ---------------------------

#define BATTERY_CAPACITY 5000 // e.g. 800mAh battery
// DesignEnergy = BATTERY_CAPACITY(mAh) * 3.7V
#define DESIGN_ENERGY 18500
#define TERMINATE_VOLTAGE 3300 //TerminateVoltage = 3300mV
#define TAPER_CURRENT 115 //TaperCurrent = 115mA
// TAPER_RATE = (int)(BATTERY_CAPACITY / (0.1 * TAPER_CURRENT))
#define TAPER_RATE 434
#define TAPER_VOLTAGE 4200
#define SOC1_SET_THRESHOLD 10 //low battery threshold percentage interrupt
#define SOC1_CLEAR_THRESHOLD 11 //low battery threshold interrupt clear after reaching this percentage
#define FC_SET 98 //Charging terminates after this percentage
#define FC_CLEAR 95 //Flag's FC bit clear below this percentage
#define OPCONFIG 0x1DFC


typedef struct
{
uint8_t charging : 1;
uint8_t discharge : 1;
uint8_t Bat_Low : 1;
int16_t Percentage;
int16_t Current;
int16_t Design_Capacity;
int16_t Full_Capacity;
int16_t Avail_Capacity;
float Voltage;
}Battery;

typedef enum
{
SET_BATTERY_CAPACITY,
SET_OPCONFIG,
SET_DESIGN_ENERGY,
SET_TERMINATE_VOLTAGE,
SET_TAPER_RATE,
SET_TAPER_VOLTAGE,
SET_SOC1_THRESHOLD,
SET_FC_SET,
SET_FC_CLEAR,
SET_SOC1_CLEAR_THRESHOLD
}Fual_Guage_Init;

typedef enum
{
ENTER_CONFIG,
COMPUTE_BLOCK_CHKSUM,
GET_CHECKSUM,
WRITE_CHECKSUM,
EXIT_CONFIG
}Write_ExtendedData;

#define TIMER_EXPIRE FG_Timer_Flag >= 2

/* This delay is required for I2C read */
#define DELAY for(j = 0;j < 500;j++)


#define SOC1_CLR_THRESHOLD ((offset == 1) && (classID == 49))
#define DEDIGN_CAPACITY ((offset == 10) && (classID == 82))

#define FG_INITIALIZATION_COMPLETE FG_Init > SET_SOC1_CLEAR_THRESHOLD

// Parameters for the current() function, to specify which current to read
typedef enum {
AVG, // Average Current (DEFAULT)
STBY, // Standby Current
MAX // Max Current
} current_measure;

// Parameters for the capacity() function, to specify which capacity to read
typedef enum {
REMAIN, // Remaining Capacity (DEFAULT)
FULL, // Full Capacity
AVAIL, // Available Capacity
AVAIL_FULL, // Full Available Capacity
REMAIN_F, // Remaining Capacity Filtered
REMAIN_UF, // Remaining Capacity Unfiltered
FULL_F, // Full Capacity Filtered
FULL_UF, // Full Capacity Unfiltered
DESIGN // Design Capacity
} capacity_measure;

// Parameters for the soc() function
typedef enum {
FILTERED, // State of Charge Filtered (DEFAULT)
UNFILTERED // State of Charge Unfiltered
} soc_measure;

// Parameters for the soh() function
typedef enum {
PERCENT, // State of Health Percentage (DEFAULT)
SOH_STAT // State of Health Status Bits
} soh_measure;

// Parameters for the temperature() function
typedef enum {
BATTERY, // Battery Temperature (DEFAULT)
INTERNAL_TEMP // Internal IC Temperature
} temp_measure;

// Parameters for the setGPOUTFunction() funciton
typedef enum {
SOC_INT, // Set GPOUT to SOC_INT functionality
// BAT_LOW // Set GPOUT to BAT_LOW functionality <----- This is commented
} gpout_function;

///////////////////////
// General Constants //
///////////////////////
#define BQ27441_UNSEAL_KEY 0x8000 // Secret code to unseal the BQ27441-G1A
#define BQ27441_DEVICE_ID 0x0421 // Default device ID

///////////////////////
// Standard Commands //
///////////////////////
// The fuel gauge uses a series of 2-byte standard commands to enable system
// reading and writing of battery information. Each command has an associated
// sequential command-code pair.
#define BQ27441_COMMAND_CONTROL 0x00 // Control()
#define BQ27441_COMMAND_TEMP 0x02 // Temperature()
#define BQ27441_COMMAND_VOLTAGE 0x04 // Voltage()
#define BQ27441_COMMAND_FLAGS 0x06 // Flags()
#define BQ27441_COMMAND_NOM_CAPACITY 0x08 // NominalAvailableCapacity()
#define BQ27441_COMMAND_AVAIL_CAPACITY 0x0A // FullAvailableCapacity()
#define BQ27441_COMMAND_REM_CAPACITY 0x0C // RemainingCapacity()
#define BQ27441_COMMAND_FULL_CAPACITY 0x0E // FullChargeCapacity()
#define BQ27441_COMMAND_AVG_CURRENT 0x10 // AverageCurrent()
#define BQ27441_COMMAND_STDBY_CURRENT 0x12 // StandbyCurrent()
#define BQ27441_COMMAND_MAX_CURRENT 0x14 // MaxLoadCurrent()
#define BQ27441_COMMAND_AVG_POWER 0x18 // AveragePower()
#define BQ27441_COMMAND_SOC 0x1C // StateOfCharge()
#define BQ27441_COMMAND_INT_TEMP 0x1E // InternalTemperature()
#define BQ27441_COMMAND_SOH 0x20 // StateOfHealth()
#define BQ27441_COMMAND_REM_CAP_UNFL 0x28 // RemainingCapacityUnfiltered()
#define BQ27441_COMMAND_REM_CAP_FIL 0x2A // RemainingCapacityFiltered()
#define BQ27441_COMMAND_FULL_CAP_UNFL 0x2C // FullChargeCapacityUnfiltered()
#define BQ27441_COMMAND_FULL_CAP_FIL 0x2E // FullChargeCapacityFiltered()
#define BQ27441_COMMAND_SOC_UNFL 0x30 // StateOfChargeUnfiltered()

//////////////////////////
// Control Sub-commands //
//////////////////////////
// Issuing a Control() command requires a subsequent 2-byte subcommand. These
// additional bytes specify the particular control function desired. The
// Control() command allows the system to control specific features of the fuel
// gauge during normal operation and additional features when the device is in
// different access modes.
#define BQ27441_CONTROL_STATUS 0x00
#define BQ27441_CONTROL_DEVICE_TYPE 0x01
#define BQ27441_CONTROL_FW_VERSION 0x02
#define BQ27441_CONTROL_DM_CODE 0x04
#define BQ27441_CONTROL_PREV_MACWRITE 0x07
#define BQ27441_CONTROL_CHEM_ID 0x08
#define BQ27441_CONTROL_BAT_INSERT 0x0C
#define BQ27441_CONTROL_BAT_REMOVE 0x0D
#define BQ27441_CONTROL_SET_HIBERNATE 0x11
#define BQ27441_CONTROL_CLEAR_HIBERNATE 0x12
#define BQ27441_CONTROL_SET_CFGUPDATE 0x13
#define BQ27441_CONTROL_SHUTDOWN_ENABLE 0x1B
#define BQ27441_CONTROL_SHUTDOWN 0x1C
#define BQ27441_CONTROL_SEALED 0x20
#define BQ27441_CONTROL_PULSE_SOC_INT 0x23
#define BQ27441_CONTROL_RESET 0x41
#define BQ27441_CONTROL_SOFT_RESET 0x42
#define BQ27441_CONTROL_EXIT_CFGUPDATE 0x43
#define BQ27441_CONTROL_EXIT_RESIM 0x44

///////////////////////////////////////////
// Control Status Word - Bit Definitions //
///////////////////////////////////////////
// Bit positions for the 16-bit data of CONTROL_STATUS.
// CONTROL_STATUS instructs the fuel gauge to return status information to
// Control() addresses 0x00 and 0x01. The read-only status word contains status
// bits that are set or cleared either automatically as conditions warrant or
// through using specified subcommands.
#define BQ27441_STATUS_SHUTDOWNEN (1<<15)
#define BQ27441_STATUS_WDRESET (1<<14)
#define BQ27441_STATUS_SS (1<<13)
#define BQ27441_STATUS_CALMODE (1<<12)
#define BQ27441_STATUS_CCA (1<<11)
#define BQ27441_STATUS_BCA (1<<10)
#define BQ27441_STATUS_QMAX_UP (1<<9)
#define BQ27441_STATUS_RES_UP (1<<8)
#define BQ27441_STATUS_INITCOMP (1<<7)
#define BQ27441_STATUS_HIBERNATE (1<<6)
#define BQ27441_STATUS_SLEEP (1<<4)
#define BQ27441_STATUS_LDMD (1<<3)
#define BQ27441_STATUS_RUP_DIS (1<<2)
#define BQ27441_STATUS_VOK (1<<1)

////////////////////////////////////
// Flag Command - Bit Definitions //
////////////////////////////////////
// Bit positions for the 16-bit data of Flags()
// This read-word function returns the contents of the fuel gauging status
// register, depicting the current operating status.
#define BQ27441_FLAG_OT (1<<15)
#define BQ27441_FLAG_UT (1<<14)
#define BQ27441_FLAG_FC (1<<9)
#define BQ27441_FLAG_CHG (1<<8)
#define BQ27441_FLAG_OCVTAKEN (1<<7)
#define BQ27441_FLAG_ITPOR (1<<5)
#define BQ27441_FLAG_CFGUPMODE (1<<4)
#define BQ27441_FLAG_BAT_DET (1<<3)
#define BQ27441_FLAG_SOC1 (1<<2)
#define BQ27441_FLAG_SOCF (1<<1)
#define BQ27441_FLAG_DSG (1<<0)

////////////////////////////
// Extended Data Commands //
////////////////////////////
// Extended data commands offer additional functionality beyond the standard
// set of commands. They are used in the same manner; however, unlike standard
// commands, extended commands are not limited to 2-byte words.
#define BQ27441_EXTENDED_OPCONFIG 0x3A // OpConfig()
#define BQ27441_EXTENDED_CAPACITY 0x3C // DesignCapacity()
#define BQ27441_EXTENDED_DATACLASS 0x3E // DataClass()
#define BQ27441_EXTENDED_DATABLOCK 0x3F // DataBlock()
#define BQ27441_EXTENDED_BLOCKDATA 0x40 // BlockData()
#define BQ27441_EXTENDED_CHECKSUM 0x60 // BlockDataCheckSum()
#define BQ27441_EXTENDED_CONTROL 0x61 // BlockDataControl()

////////////////////////////////////////
// Configuration Offset //
////////////////////////////////////////
#define CAPACITY_OFFSET 10
#define DESIGN_ENERGY_OFFSET 12
#define TERMINATE_VTG_OFFSET 16
#define TAPERRATE_OFFSET 27
#define TAPER_VTG_OFFSET 29
#define OPCONFIG_OFFSET 0
#define SOC1_OFFSET 0
#define SOC1_CLEAR_OFFSET 1
#define FC_SET_OFFSET 5
#define FC_CLEAR_OFFSET 6

////////////////////////////////////////
// Configuration Class, Subclass ID's //
////////////////////////////////////////
// To access a subclass of the extended data, set the DataClass() function
// with one of these values.
// Configuration Classes
#define BQ27441_ID_SAFETY 2 // Safety
#define BQ27441_ID_CHG_TERMINATION 36 // Charge Termination
#define BQ27441_ID_CONFIG_DATA 48 // Data
#define BQ27441_ID_DISCHARGE 49 // Discharge
#define BQ27441_ID_REGISTERS 64 // Registers
#define BQ27441_ID_POWER 68 // Power
// Gas Gauging Classes
#define BQ27441_ID_IT_CFG 80 // IT Cfg
#define BQ27441_ID_CURRENT_THRESH 81 // Current Thresholds
#define BQ27441_ID_STATE 82 // State
// Ra Tables Classes
#define BQ27441_ID_R_A_RAM 89 // R_a RAM
// Calibration Classes
#define BQ27441_ID_CALIB_DATA 104 // Data
#define BQ27441_ID_CC_CAL 105 // CC Cal
#define BQ27441_ID_CURRENT 107 // Current
// Security Classes
#define BQ27441_ID_CODES 112 // Codes

/////////////////////////////////////////
// OpConfig Register - Bit Definitions //
/////////////////////////////////////////
// Bit positions of the OpConfig Register
#define BQ27441_OPCONFIG_BIE (1<<13)
#define BQ27441_OPCONFIG_BI_PU_EN (1<<12)
#define BQ27441_OPCONFIG_GPIOPOL (1<<11)
#define BQ27441_OPCONFIG_SLEEP (1<<5)
#define BQ27441_OPCONFIG_RMFCC (1<<4)
#define BQ27441_OPCONFIG_BATLOWEN (1<<2)
#define BQ27441_OPCONFIG_TEMPS (1<<0)


// Function Declaration
uint8_t begin(void);
uint8_t setCapacity(uint16_t capacity);
uint16_t voltage(void);
int16_t current(current_measure type);
uint16_t capacity(capacity_measure type);
int16_t power(void);
uint16_t soc(soc_measure type);
uint8_t soh(soh_measure type);
uint16_t temperature(temp_measure type);
uint16_t deviceType(void);
uint8_t enterConfig(uint8_t userControl);
uint8_t exitConfig(uint8_t resim);
uint16_t flags(void);
uint16_t status(void);
uint8_t sealed(void);
uint8_t seal(void);
uint8_t unseal(void);
uint16_t opConfig(void);
uint16_t readWord(uint16_t subAddress);
uint16_t readControlWord(uint16_t function);
uint8_t executeControlWord(uint16_t function);
uint8_t blockDataControl(void);
uint8_t blockDataClass(uint8_t id);
uint8_t blockDataOffset(uint8_t offset);
uint8_t blockDataChecksum(void);
uint8_t readBlockData(uint8_t offset);
uint8_t writeBlockData(uint8_t offset, uint8_t data);
uint8_t computeBlockChecksum(void);
uint8_t writeBlockChecksum(uint8_t csum);
uint16_t readExtendedData(uint8_t classID, uint8_t offset);
uint8_t writeExtendedData(uint8_t classID, uint8_t offset, uint8_t * data, uint8_t len);
uint8_t softReset(void);
uint8_t setDesign_Energy(uint16_t capacity);
uint8_t setTerminate_Voltage(uint16_t capacity);
uint8_t setTaper_Rate(uint16_t capacity);
uint16_t my_readBlockData(uint8_t offset);
void Fualguage_initialize(void);
void Fualguage_Parameter(void);
uint8_t setTaper_Voltage(uint16_t capacity);
uint8_t setGPOUT(uint16_t capacity);
uint8_t Set_SOC1_Threshold(uint16_t capacity);
uint8_t Clear_SOC1_Threshold(uint16_t capacity);
void read_battery_percentage(void);
void Check_Battery_Chg_Dischg(void);
uint8_t Set_FcSet_Threshold(uint16_t capacity);
uint8_t Set_FcClear_Threshold(uint16_t capacity);
void FG_I2C_Read(uint8_t Address,uint8_t read_bytes);
void FG_I2C_Write(uint8_t Address,uint8_t write_bytes,uint8_t *data);

#endif