This is a library for the MAX17055 Li+ Battery Fuel Gauge.
Fork of max17055 by
Diff: max17055.cpp
- Revision:
- 7:479a36909ced
- Parent:
- 6:5ced10109ebf
- Child:
- 8:ca8765c30ed2
diff -r 5ced10109ebf -r 479a36909ced max17055.cpp --- a/max17055.cpp Thu Oct 05 02:37:59 2017 +0000 +++ b/max17055.cpp Tue Oct 10 00:06:40 2017 +0000 @@ -112,16 +112,16 @@ int MAX17055::writeReg(Registers_e reg_addr, uint16_t reg_data) { - + uint16_t mask = 0x00FF; uint8_t dataLSB; uint8_t dataMSB; - dataLSB = reg_data & 0x00FF; - dataMSB = (reg_data >> 8) & 0x00FF; + dataLSB = reg_data & mask; + dataMSB = (reg_data >> 8) & mask; - char add_plus_data[3] = {reg_addr, dataLSB, dataMSB}; + char addr_plus_data[3] = {reg_addr, dataLSB, dataMSB}; - if ( m_i2cBus.write(I2C_W_ADRS, add_plus_data, 3, false) == 0) + if ( m_i2cBus.write(I2C_W_ADRS, addr_plus_data, 3, false) == 0) return 1; else return 0; @@ -143,8 +143,7 @@ int32_t MAX17055::readReg(Registers_e reg_addr, uint16_t &value) { int32_t result; - //int16_t value2; - //int16_t twoBytes; + uint16_t mask = 0x00FF; char local_data[1]; local_data[0] = reg_addr; char read_data[2]; @@ -153,7 +152,7 @@ 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])); + value = ( ((read_data[1] & mask) << 8) + (read_data[0])); result = 1; } } @@ -200,7 +199,7 @@ if (ret<0) return ret; - else + else return 1; } @@ -217,21 +216,21 @@ */ -int MAX17055::init(max17055_platform_data des_data) +int MAX17055::init(platform_data des_data) { int status, ret; - uint16_t read_data, hibcfg_value, dpacc, reg; + uint16_t read_data, hibcfg_value, reg; - status = readReg(MAX17055_VERSION_REG, read_data); + status = readReg(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); + readReg(STATUS_REG, read_data); if (!(read_data & MAX17055_STATUS_POR ) ) return -1; //POR is not set. Skip Initialization. @@ -239,57 +238,46 @@ /* Step 1: Check if FStat.DNR == 0 */ // Do not continue until FSTAT.DNR == 0 printf("step 0 check \r\n"); - + int time_out = 500; - ret = max17055_poll_flag_clear (MAX17055_FSTAT_REG, MAX17055_FSTAT_DNR, time_out); - if (ret < 0){ + ret = poll_flag_clear(FSTAT_REG, MAX17055_FSTAT_DNR, time_out); + if (ret < 0) { printf("Unsuccessful init: Data Not Ready!\n"); return ret; } /* Force exit from hibernate */ hibcfg_value = forcedExitHyberMode(); - + printf("step 1 check \r\n"); /* Step 2: Initialize configuration */ switch (1) { case MODEL_LOADING_OPTION1: /* Step 2.1: Option 1 EZ Config */ - writeReg(MAX17055_DESIGNCAP_REG, des_data.designcap); - writeReg(MAX17055_DQACC_REG, des_data.designcap >> 5); - writeReg(MAX17055_ICHGTERM_REG, des_data.ichgterm); - writeReg(MAX17055_VEMPTY_REG, des_data.vempty); - - if (design_data.vcharge > 4275) { //Need to know what this 4275 is - dpacc = (des_data.designcap >> 5) * 0xC800 / des_data.designcap; - writeReg(MAX17055_DPACC_REG, dpacc); - writeReg(MAX17055_MODELCFG_REG, 0x8400); //Why 0x8400 - } else { - dpacc = (des_data.designcap >> 5) * 0xAC6A / des_data.designcap; - writeReg(MAX17055_DPACC_REG, dpacc); - writeReg(MAX17055_MODELCFG_REG, 0x8000); - } + EZconfig_init(des_data); /* Poll ModelCFG.ModelRefresh bit for clear */ - ret = max17055_poll_flag_clear(MAX17055_MODELCFG_REG, MAX17055_MODELCFG_REFRESH, 500); + int time_out = 500; //msec + ret = poll_flag_clear(MODELCFG_REG, MAX17055_MODELCFG_REFRESH, time_out); if(ret < 0) { //dev_err(priv->dev, "Option1 model refresh not completed!\n"); return ret; } + break; } /* Restore original HibCfg */ - writeReg(MAX17055_HIBCFG_REG, hibcfg_value); + writeReg(HIBCFG_REG, hibcfg_value); printf("Last section check \r\n"); /* Optional step - alert threshold initialization */ - //max17055_set_alert_thresholds(priv); + //set_alert_thresholds(priv); /* Clear Status.POR */ - readReg(MAX17055_STATUS_REG, reg); - write_and_verify_reg(MAX17055_STATUS_REG, (reg & ~MAX17055_STATUS_POR)); + readReg(STATUS_REG, reg); + write_and_verify_reg(STATUS_REG, (reg & ~MAX17055_STATUS_POR)); return 1; } @@ -310,13 +298,13 @@ * -1 on Failure */ -int MAX17055::max17055_poll_flag_clear (Registers_e reg_addr, int mask, int timeout) +int MAX17055::poll_flag_clear (Registers_e reg_addr, int mask, int timeout) { uint16_t data; int ret; do { - wait(50); + wait_ms(10); ret = readReg(reg_addr, data); if(ret < 0) return ret; @@ -324,7 +312,7 @@ if(!(data & mask)) return 1; - timeout -= 50; + timeout -= 10; } while(timeout > 0); return -1; @@ -340,35 +328,31 @@ * 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 * +* \retval temperature value * -1 if errors exist */ -int MAX17055::get_temperature(int *temp) +int MAX17055::get_temperature() { int ret; uint16_t data; - ret = readReg(MAX17055_TEMP_REG, data); + ret = readReg(TEMP_REG, data); if (ret < 0) return ret; - *temp = data; /* The value is signed. */ - if (*temp & 0x8000) - *temp |= 0xFFFF0000; + if (data & 0x8000) + data |= 0xFFFF0000; /* The value is converted into centigrade scale */ /* Units of LSB = 1 / 256 degree Celsius */ - *temp >>= 8; + data >>= 8; - return 1; + return data ; } @@ -389,18 +373,265 @@ uint16_t hibcfg; /* Force exit from hibernate */ - //STEP 0: Store original HibCFG value - readReg(MAX17055_HIBCFG_REG, hibcfg); + readReg(HIBCFG_REG, hibcfg); //STEP 1: Write to Soft-Wakeup Commannd Register - writeReg(MAX17055_VFSOC0_QH0_LOCK_REG, 0x90); //Soft-Wakeup from hybernate + writeReg(VFSOC0_QH0_LOCK_REG, 0x90); //Soft-Wakeup from hybernate //STEP 2: Write to Hibernate Configuration register - writeReg(MAX17055_HIBCFG_REG, 0x0); //disable hibernate mode + writeReg(HIBCFG_REG, 0x0); //disable hibernate mode //STEP 3:Write to Soft-Wakeup Commannd Register - writeReg(MAX17055_VFSOC0_QH0_LOCK_REG, 0x0); //Clear All commnads + writeReg(VFSOC0_QH0_LOCK_REG, 0x0); //Clear All commnads return hibcfg; } + + +//////////////////////////////////////////////////////////////////////////////// + +/** +* \brief EZ COnfing Init function +* \par Details +* This function implements the steps for the EZ confing m5 FuelGauge +* +* \retval returns TBD +* +*/ + + +uint16_t MAX17055::EZconfig_init(platform_data des_data) +{ + const int charger_th = 4275; + const int chg_V_high = 51200; + const int chg_V_low = 44138; + const int param_EZ_FG1 = 0x8400; + const int param_EZ_FG2 = 0x8000; + int ret; + uint16_t dpacc; + + + /* Step 2.1: Option 1 EZ Config */ + writeReg(DESIGNCAP_REG, des_data.designcap); + writeReg(DQACC_REG, des_data.designcap >> 5); + writeReg(ICHGTERM_REG, des_data.ichgterm); + writeReg(VEMPTY_REG, des_data.vempty); + + if (des_data.vcharge > charger_th) { + dpacc = (des_data.designcap >> 5) * chg_V_high / des_data.designcap; + writeReg(DPACC_REG, dpacc); + writeReg(MODELCFG_REG, param_EZ_FG1); //Why 0x8400 + } else { + dpacc = (des_data.designcap >> 5) * chg_V_low / des_data.designcap; + writeReg(DPACC_REG, dpacc); + writeReg(MODELCFG_REG, param_EZ_FG2); + } + + + return ret; + +} + + +//////////////////////////////////////////////////////////////////////////////// + +/** +* \brief Get State Of Charge(SOC) 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 - SOC data from the REPSOC_REG register +* \retval 1 on success +* +* -1 if errors exist +*/ + + +int MAX17055::get_SOC() +{ + + int ret; + uint16_t data; + + ret = readReg(REPSOC_REG, data); + if (ret < 0) + return ret; + + data = data >> 8; /* RepSOC LSB: 1/256 % */ + + return data; +} + + +/////////////////////////////////////////////////////////////////////////////// + +/** +* \brief Get the remaining Time to Empty(TTE) Function for MAX17055 +* \par Details +* This function sends a request to access the internal register +* of the MAX17055 +* +* \retval tte_data - Time to Empty data from the TTE_REG register +* +* -1 if errors exist +*/ + +int MAX17055::get_TTE() +{ + + int ret; + uint16_t data; + + ret = readReg(TTE_REG, data); + if (ret < 0) + return ret; + else + data = (data * 45) >> 3; /* TTE LSB: 5.625 sec */ + + return data; +} + + +//////////////////////////////////////////////////////////////////////////// + +/** +* \brief Get voltage of the cell Function for MAX17055 +* \par Details +* This function sends a request to access the internal register +* of the MAX17055 to read the voltage of the cell +* +* \retval vcell_data - vcell data from the VCELL_REG register +* +* -1 if errors exist +*/ + + +int MAX17055::get_Vcell() +{ + + int ret; + uint16_t vcell_data; + + ret = readReg(VCELL_REG, vcell_data); + if (ret < 0) + return ret; + else + //printf("Vcell Reg= %d \r\n",vcell_data); + ret = lsb_to_uvolts(vcell_data); + //printf("Vcell Conv= %d \r\n",ret); + return ret; + +} + + +//////////////////////////////////////////////////////////////////////////// + +/** +* \brief Get current Function for MAX17055 +* \par Details +* This function sends a request to access the internal register +* of the MAX17055 to read the current register. +* +* \retval curr_data - vcell data from the VCELL_REG register +* +* -1 if errors exist +*/ + + +int MAX17055::get_Current( platform_data des_data ) +{ + + int ret,design_rsense; + uint16_t data; + + ret = readReg(CURRENT_REG, data); + if (ret < 0) + return ret; + else + design_rsense = des_data.rsense; + ret = raw_current_to_uamps((uint32_t)data, design_rsense); + return ret; + +} + + +//////////////////////////////////////////////////////////////////////////// + +/** +* \brief Get Average Current Function for MAX17055 +* \par Details +* This function sends a request to access the internal register +* of the MAX17055 to read the average current register. +* +* \retval curr_data - vcell data from the AVGCURRENT_REG register +* +* -1 if errors exist +*/ + + +int MAX17055::get_AvgCurrent( platform_data des_data ) +{ + + int ret, design_rsense; + uint16_t data; + uint32_t aveCurr_data; + + ret = readReg(AVGCURRENT_REG, data); + if (ret < 0) + return ret; + else + aveCurr_data = data; + design_rsense = des_data.rsense; + aveCurr_data = raw_current_to_uamps(aveCurr_data, design_rsense); + return aveCurr_data; + +} + +/////////////////////////////////////////////////////////////////////////////// + +/** +* \brief lsb_to_uvolts Converssion Function +* \par Details +* This function takes the lsb value of the register and convert it +* to uvolts +* +* \param[in] lsb - value of register lsb +* \retval lsb - converted lsb to uvolts +* +*/ + +int MAX17055:: lsb_to_uvolts(uint16_t lsb) +{ + int store; + store = (lsb * 625) / 8; /* 78.125uV per bit */ + return store; +} + + +/////////////////////////////////////////////////////////////////////////////// + +/** +* \brief raw_current_to_uamp Converssion Function +* \par Details +* This function takes the raw current value of the register and +* converts it to uamps +* +* \param[in] curr - raw current value of register +* \retval res - converted raw current to uamps - Signed 2's complement +* +*/ + +int MAX17055::raw_current_to_uamps(uint32_t curr, int rsense_value) +{ + int res = curr; + /* Negative */ + if (res & 0x8000) { + res |= 0xFFFF0000; + } else { + res *= 1562500 /(rsense_value * 1000); //Change to interact with the rsense of customer + } + return res; +} \ No newline at end of file