This is a library for the MAX17055 Li+ Battery Fuel Gauge.

Dependents:   Low_Power_Long_Distance_IR_Vision_Robot MAX17055_EZconfig MAX17055_EZconfig_Sample Low_Power_Long_Distance_IR_Vision_Robot

Fork of max17055 by Maxim Integrated

max17055.cpp

Committer:
fneirab
Date:
2017-09-27
Revision:
4:a4d6ae2182c2
Parent:
3:f77a8345b0e3
Child:
5:a18a189588dc

File content as of revision 4:a4d6ae2182c2:

/******************************************************************//**
* @file max17055.cpp
*
* @author Felipe Neira - Maxim Integrated - TTS
*
* @version 1.0
*
* Started: 11SEP17
*
* Updated: 
*
* @brief Source file for MAX31855 class
*
********************************************************************************
* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*
******************************************************************************/

#include "mbed.h"
#include "max17055.h"

struct max17055_priv {
    struct i2c_client       *client;
    struct device           *dev;
    struct regmap           *regmap;
    struct power_supply     battery;
    struct max17055_platform_data   *pdata;
    struct work_struct      init_worker;
    struct attribute_group  *attr_grp;
};


MAX17055::MAX17055(I2C &i2c): 
m_i2cBus(i2c)
{
  //empty block
}

MAX17055::~MAX17055()
{
    //empty block
}
///////////////////////////////////////////////////////////////////////////////

/**
* \brief        Write a value to a MAX17055 register
* \par          Details
*               This function writes a value to a MAX17055 register
*
* \param[in]    reg_addr - register address
* \param[in]    reg_data - register data
*
* \retval       1 on success
*/

int MAX17055::writeReg(Registers_e reg_addr, uint16_t reg_data)
{

    
    uint8_t dataLSB;
    uint8_t dataMSB;
    
    dataLSB = reg_data & 0x00FF;
    dataMSB = (reg_data >> 8) & 0x00FF; 
    
    char add_plus_data[3] = {reg_addr, dataLSB, dataMSB};
    
    if ( m_i2cBus.write(I2C_W_ADRS, add_plus_data, 3, false) == 0)
        return 1;
    else
        return 0;

}
///////////////////////////////////////////////////////////////////////////////
/**
* \brief        Read a MAX17055 register
* \par          Details
*               This function reads a MAX17055 register
*
* \param[in]    reg_addr   - register address
* \param[out]   &value   - pointer that stores the register data
*
* \retval       1 on success
*/


int32_t MAX17055::readReg(Registers_e reg_addr, uint16_t &value)
{
    int32_t result;
    //int16_t value2;
    //int16_t twoBytes;
    char local_data[1];
    local_data[0] = reg_addr;
    char read_data[2];
 
    result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
    if(result == 0) 
    {
        result = m_i2cBus.read(I2C_R_ADRS, read_data , 2, false);
        if (result == 0)
        {
            value = ( ((read_data[1] & 0x00FF) << 8) + (read_data[0]));
            result = 1;
        } 
    }
    
    return result;
  
}

///////////////////////////////////////////////////////////////////////////////
/**
* \brief        Write and Verify a MAX17055 register
* \par          Details
*               This function wites and verifies if the writing process was successful
*
* \param[in]    reg_addr     - register address
* \param[out]   reg_data     - the variable that contains the data to write 
*                                to the register address
*
* \retval       1 on success
*/


int MAX17055::write_and_verify_reg (MAX17055::Registers_e reg_addr, uint16_t reg_data)
{   
    int retries = 8;
    int ret;
    int statusRead;
    int statusWrite;
    uint16_t read_data;
    
    do {
        statusWrite = writeReg(reg_addr, reg_data);
        if (statusWrite != 1)
            ret = -1;
        wait_ms(3);
        statusRead = readReg(reg_addr, read_data); 
        if  (statusRead != 1)
            ret = -2;
        if (read_data != reg_data){
            ret = -3;
            retries--;
        }
    }while (retries && read_data != reg_data);
    
    if (ret<0)
    {
        return ret;
    } else
        return 1;
}

////////////////////////////////////////////////////////////////////////////////

/**
* \brief        Initialise Function for MAX17055
* \par          Details
*               This function intitializes the MAX17055
*
* \retval       1 on success 
*               0 if device is not present
*              -1 if errors exist
*/
    
    
int MAX17055::init()
{
    int status;
    uint16_t read_data, hibcfg_value;
    
    status = readReg(MAX17055_VERSION_REG, read_data);
    if (status == 0)
        return status;  //Device is not present in the i2c Bus
         
    /* Step 0: Check for POR */
    /* Skip load model if POR bit is cleared */
    
    readReg(MAX17055_STATUS_REG, read_data);

    if (!(read_data & MAX17055_STATUS_POR ) )
        return -1;  //POR is not set. Skip Initialization. 

    /* Step 1: Check if FStat.DNR == 0 */
    // Do not continue until FSTAT.DNR == 0
    
    while(readReg(MAX17055_FSTAT_REG, read_data)&1)
    {
        wait_ms(10);//10 ms wait empty loop
    }
    
     /* Force exit from hibernate */
     hibcfg_value = forcedExitHyberMode();
    
    return 1;
}  

////////////////////////////////////////////////////////////////////////////////

/**
* \brief        Get Internal Temperature Function for MAX17055
* \par          Details
*               This function sends a request to access the internal
*               of the MAX17055
*
* \param[in]    reg_addr     - register address
* \param[out]   reg_data     - the variable that contains the data to write 
*                                to the register address
* \retval       1 on success 
*   
*              -1 if errors exist
*/
    
    
int MAX17055::get_temperature(int *temp)
{
    
    int ret;
    uint16_t data;
    
    ret = readReg(MAX17055_TEMP_REG, data);
    if (ret < 0)
        return ret;

    *temp = data;
    /* The value is signed. */
    if (*temp & 0x8000)
        *temp |= 0xFFFF0000;

    /* The value is converted into centigrade scale */
    /* Units of LSB = 1 / 256 degree Celsius */
    *temp >>= 8;

    return 1;
}  


////////////////////////////////////////////////////////////////////////////////

/**
* \brief        Forced Exit Hibernate Mode Function for MAX17055
* \par          Details
*               This function executes a force exit from hibernate mode. 
*
* \retval       returns HibCFG original value before forced Exit Hybernate mode
*
*/
    
    
uint16_t MAX17055::forcedExitHyberMode()
{
    uint16_t hibcfg;
    
/* Force exit from hibernate */

    //STEP 0: Store original HibCFG value
    readReg(MAX17055_HIBCFG_REG, hibcfg);

    //STEP 1: Write to Soft-Wakeup Commannd Register
    writeReg(MAX17055_VFSOC0_QH0_LOCK_REG, 0x90); //Soft-Wakeup from hybernate
    
    //STEP 2: Write to Hibernate Configuration register
    writeReg(MAX17055_HIBCFG_REG, 0x0); //disable hibernate mode
    
    //STEP 3:Write to Soft-Wakeup Commannd Register
    writeReg(MAX17055_VFSOC0_QH0_LOCK_REG, 0x0); //Clear All commnads
    
    return hibcfg;
} 
  
//step_1:
//        // Wait until MAX17055 complete setup operations (Data is Ready)
//        while(readReg(F_STAT) & 0x0001) delay(10);
//        /***************************************************************/
//        // Setting up or initializing charging configurations down here , EZ CONFIG because no .INI file
//        // FIXX:: DOUBLE CHECK THE INITIALIZATION VALUES
//        // init values is claculated based on the register lsb's default value page 1 software implementation UG
//        /* Capacity is in mAH and 1 bit is 0.5mAH)*/
//        temp = battery->capacity*2;
//        writeReg(DESIGN_CAP, temp);
//        writeReg(DQ_A_CC, temp/32);
//        /* Current measurement, assuming current input in mA */
//        temp = battery->currentTerm*1000/1.5625;
//        writeReg(ICHG_TERM, temp);
//        /* FIXX: DOUBLE CHECK Vempty register (v empty | v recovery), I am assuming that
//        VE resolution is 10mV and VR resolution is 40mV (programmer's guide)*/
//        temp =((battery->voltageMin/10) << 7 | (battery->voltageNom)/40);
//        writeReg(V_EMPTY ,temp);
//
//        data = readReg(HIB_CFG); // Store original HIB_CFG inside
//        writeReg((Registers_e)0x60, 0x90); // Exit hibernate mode step 1
//        writeReg(CONFIG_2, 0x0); // Exit hibernate mode step 2
//        writeReg((Registers_e)0x60, 0x0); // Exit hibernate mode step 3
//
//        temp = battery->capacity*2;
//        if (battery->voltageMax > 4.275) {
//            writeReg(DP_A_CC, (temp/32)*51200/temp); // Write dPAcc
//            writeReg(MODEL_CFG, 0x8400);    // Write ModelCFG
//        } else {
//            writeReg(DP_A_CC, (temp/32)*44138/temp);
//            writeReg(MODEL_CFG, 0x8000);
//        }
//        // Poll ModelCFG.refresh (highest bit), proceed to next step when ModelCFG.Refresh = 0.
//        while(readReg(MODEL_CFG) & 0x8000) delay(10);
//        writeReg(HIB_CFG, data);    // Restore the original HibCFG value
//        /***************************************************************/
//    }
//    /***************************************************************/
//    // FIXX: DOUBLE CHECK, STEP 4 IN PROGRAMMER'S GUIDE
//    data = readReg(STATUS); // read status register
//
//    if (write_and_verify_reg(STATUS, data & 0xFFFD) != E_NO_ERROR) {
//        return -1;
//    }
//    // Check whether there is saved history parameters
//    temp = saved_param->rcomp0;
//    temp &= saved_param ->temp_co;
//    temp &= saved_param->full_cap_rep;
//    temp &= saved_param->cycles;
//    temp &= saved_param->full_cap_nom;
//    // If there is no history setup the battery
//    if (temp == 0) {
//        // Check for MAX17055 reset
//        StatusPOR = readReg(STATUS) & 0x0002;
//        if (StatusPOR == 1) goto step_1;
//    }
//step_4P3:
//    // Read the reported capacity(mAH) and SOC (percentage)
//    RepCap = readReg(REP_CAP);
//    RepSOC = readReg(REP_SOC);
//
//    // Read the TTE (in 5.625s)
//    TTE_val = ((float)(readReg(TTE))) * 5.625;
//
//    // Save learned parameters
//    saved_param->rcomp0 = readReg(R_COMP_0);
//    saved_param->temp_co = readReg(TEMP_CO);
//    saved_param->full_cap_rep = readReg(FULL_CAP_REP);
//    saved_param->cycles = readReg(CYCLES);
//    saved_param->full_cap_nom = readReg(FULL_CAP_NOM);
//
//    // Restoring Capacity Parameters
//    if (write_and_verify_reg(R_COMP_0, saved_param->rcomp0) != E_NO_ERROR) {
//        return -1;
//    }
//    if (write_and_verify_reg(TEMP_CO, saved_param->temp_co) != E_NO_ERROR) {
//        return -1;
//    }
//    if (write_and_verify_reg(FULL_CAP_REP, saved_param->full_cap_rep) != E_NO_ERROR) {
//        return -1;
//    }
//
//    delay(350);
//    // Restore FullCap
//    temp = readReg(FULL_CAP_NOM); // Read full_cap_nom
//    data = (readReg(MIX_SOC)*temp)/25600; // MIXCAP
//    if (write_and_verify_reg(MIX_CAP, data) != E_NO_ERROR) {
//        return -1;
//    }
//    if (write_and_verify_reg(FULL_CAP_REP, temp) != E_NO_ERROR) {
//        return -1;
//    }
//    data = saved_param->full_cap_nom/16; // This act as dQacc
//    if (write_and_verify_reg(DP_A_CC, 0x0C80) != E_NO_ERROR) {
//        return -1;
//    }
//    if (write_and_verify_reg(DQ_A_CC, temp) != E_NO_ERROR) {
//        return -1;
//    }
//
//    delay(350);
//    // Restore Cycles Register
//    if (write_and_verify_reg(CYCLES, saved_param->cycles) != E_NO_ERROR) {
//        return -1;
//    }
//
//return E_NO_ERROR;
//
//
//saved_fuel_gauge_params_t default_param = {0,0,0,0,0};