LTC2942 interface with interrupt and battery register calculations

LTC294X.cpp

Committer:
kaushalpkk
Date:
2019-08-08
Revision:
1:547ec53dc37d
Parent:
0:f9e13080204a

File content as of revision 1:547ec53dc37d:

#include "mbed.h"
#include "LTC294X.h"

LTC29421::LTC29421(PinName _a,PinName _b,PinName _c,void (*interruptFunc)()):
    _i2c(_a, _b),_alcc(_c){

    _i2c.frequency(400000);
    _alcc.fall(interruptFunc);
    _addr = 0xC8;
    _battMax = 0x00;
    _presc = 128;
    DEBUG("WARNING! use setPrescAndBattCap() to set Battery Capacity\r\n");

}

LTC29421::LTC29421(PinName _a,PinName _b,PinName _c,void (*interruptFunc)(), float battCap):
    _i2c(_a, _b),_alcc(_c){

    _i2c.frequency(400000);
    _alcc.fall(interruptFunc);
    _addr = 0xC8;
    
    setPrescAndBattCap(battCap);
}

void LTC29421::setPrescAndBattCap(float battcap){
    _battCap = battcap;
    float posM = (char)23*_battCap;
    for(int i=0; i<8; i++){
        if(pow(2,(float)i) >= posM){
            _presc = pow(2,(float)i);
            setPrescaler((int)_presc);
            break;
        }
    } 
    DEBUG("Prescaler 'M' set to %d\r\n", (int)_presc);
    _battMax = ((_battCap*1000)*128)/(_presc*0.085);
    DEBUG("Battery capacity computed as %.2f Ah with bat max 0x%X  \r\n", _battCap, (int)_battMax);    
}


void LTC29421::setADCMode(int modeSel){
    char ans = getControlReg();

    switch(modeSel) {
        case ADC_AUTO:
            sbi(ans, ADC_VOLT_MODE);
            sbi(ans, ADC_TEMP_MODE);
            break;
        case ADC_VOLT:
            sbi(ans, ADC_VOLT_MODE);
            cbi(ans, ADC_TEMP_MODE);
            break;
        case ADC_TEMP:
            cbi(ans, ADC_VOLT_MODE);
            sbi(ans, ADC_TEMP_MODE);
            break;
        case ADC_SLEEP:
            cbi(ans, ADC_VOLT_MODE);
            cbi(ans, ADC_TEMP_MODE);
            break;
        default:

            break;
    }
    setControlReg(ans);
}

void LTC29421::setPrescaler(int val){
    if(val <= 7) {
        char ans = getControlReg();

        if((val & 0x01) != 0) {
            sbi(ans, PRESCALER_0);
        } else {
            cbi(ans, PRESCALER_0);
        }
        if((val & 0x02) != 0) {
            sbi(ans, PRESCALER_1);
        } else {
            cbi(ans, PRESCALER_1);
        }
        if((val & 0x04) != 0) {
            sbi(ans, PRESCALER_2);
        } else {
            cbi(ans, PRESCALER_2);
        }
        setControlReg(ans);

        _presc = (float)getPrescaler();

    } else {

    }
}

int LTC29421::getPrescaler(){
    char res = 0x00;
    char ans = getControlReg();

    if((ans & _BV(PRESCALER_0)) != 0) {
        sbi(res, 0x00);
    } else {
        cbi(res, 0x00);
    }
    if((ans & _BV(PRESCALER_1)) != 0) {
        sbi(res, 0x01);
    } else {
        cbi(res, 0x01);
    }
    if((ans & _BV(PRESCALER_2)) != 0) {
        sbi(res, 0x02);
    } else {
        cbi(res, 0x02);
    }
    ans = getControlReg();
    return (int)(pow(2,(float)ans));

}

void LTC29421::configALCC(int modeSel){
    char ans = getControlReg();

    switch(modeSel) {
        case ALCC_ALERT:
            sbi(ans, ALCC_ALERT_MODE);
            cbi(ans, ALCC_CHRGC_MODE);
            break;
        case ALCC_CCOMP:
            cbi(ans, ALCC_ALERT_MODE);
            sbi(ans, ALCC_CHRGC_MODE);
            break;
        case ALCC_OFF:
            cbi(ans, ALCC_ALERT_MODE);
            cbi(ans, ALCC_CHRGC_MODE);
            break;
        default:

            break;
    }
    setControlReg(ans);
}

void LTC29421::shutdown(){
    char ans = 0x00;
    ans = getControlReg();
    sbi(ans,IC_SHUTDOWN);
    setControlReg(ans);
}

void LTC29421::wake(){
    char ans = 0x00;
    ans = getControlReg();
    cbi(ans,IC_SHUTDOWN);
    setControlReg(ans);
}

int LTC29421::accumulatedChargeReg(){
    char inn = ACC_MSB;
    char outt[2];
    _i2c.write( _addr, &inn, 1 , true);
    _i2c.read( _addr, outt, 2 );
    int accChg = (int)outt[0];
    accChg = (accChg*256)+ outt[1];
    return accChg;
}

float LTC29421::accumulatedCharge(){
    int reg = accumulatedChargeReg();
    float res = ((float)accumulatedChargeReg()/_battMax)*100;
    return res;
}

void LTC29421::accumulatedChargeReg(int inp){
    shutdown();
    char cmd[3];
        
    cmd[0] = ACC_MSB;
    cmd[1] = (0xFF00 & inp) >> 8;
    cmd[2] = (0x00FF & inp);
    _i2c.write(_addr, cmd, 3, true);
    wake();
}

void LTC29421::accumulatedCharge(float inp){
    inp = (inp/100)*_battMax;
    accumulatedChargeReg(inp);
}

void LTC29421::setChargeThresholdLow(float prect){
    char cmd[3];
    prect = (prect/100)*_battMax;
 
    cmd[0] = CHRG_THL_MSB;
    cmd[1] = (0xFF00 & (int)prect) >> 8;
    cmd[2] = (0x00FF & (int)prect);
    _i2c.write(_addr, cmd, 2, true);        
}

void LTC29421::setChargeThresholdHigh(float prect){
    char cmd[3];
    prect = (prect/100)*_battMax;
 
    cmd[0] = CHRG_THH_MSB;
    cmd[1] = (0xFF00 & (int)prect) >> 8;
    cmd[2] = (0x00FF & (int)prect);
    _i2c.write(_addr, cmd, 2, true);            
}

float LTC29421::voltage(){
    char inn = VOLT_MSB;
    char outt[2];
    _i2c.write( _addr, &inn, 1 ,true );
    _i2c.read( _addr, outt, 2 );
    int vtemp = (int)outt[0];
    vtemp = (vtemp*256)+ outt[1];
    float vol = 6 * ((float)vtemp / 65535);
    return vol;
}

void LTC29421::setVoltageThresholdLow(float inp){
    char cmd[2];
    int ans = (int)(inp *65535)/6;
    ans = ans >> 8;
    cmd[0] = VOLT_THL;
    cmd[1] = (char)ans;
    _i2c.write(_addr, cmd, 2, true);            
}

void LTC29421::setVoltageThresholdHigh(float inp){
    char cmd[2];
    int ans = (int)(inp *65535)/6;
    ans = ans >> 8;
    cmd[0] = VOLT_THH;
    cmd[1] = (char)ans;
    _i2c.write(_addr, cmd, 2, true);            
}


float LTC29421::temperature(){
    char inn = TEMP_MSB;
    char outt[2];
    _i2c.write( _addr, &inn, 1 ,true );
    _i2c.read( _addr, outt, 2 );
    int ttemp = (int)outt[0];
    ttemp = (ttemp*256)+ outt[1];
    float tempp = (600 * ((float)ttemp / 65535)) - 273.15;
    return tempp;
}

void LTC29421::setTemperatureThresholdLow(float inp){
    int ans = (int)(((inp+273.15)*65535)/600);
    ans = ans >> 8;
    char cmd[2];
    cmd[0] = TEMPERATURE_THL;
    cmd[1] = ans;
    _i2c.write(_addr, cmd, 2, true);
}

void LTC29421::setTemperatureThresholdHigh(float inp){
    int ans = (int)(((inp+273.15)*65535)/600);
    ans = ans >> 8;
    char cmd[2];
    cmd[0] = TEMPERATURE_THH;
    cmd[1] = ans;
    _i2c.write(_addr, cmd, 2, true);   
}

void LTC29421::readAll(){
    char cmd[16];
    cmd[0] = REG_STATUS;
    _i2c.write(_addr, cmd, 1, true);
    _i2c.read(_addr, cmd, 16); // read the two-byte echo result
    DEBUG("===================================================\r\n");
    DEBUG("REG_STATUS          [%X] \r\n",cmd[REG_STATUS]);    
    DEBUG("REG_CONTROL         [%X] \r\n",cmd[REG_CONTROL]);    
    DEBUG("ACC_CHARGE          [%X %X] \r\n",cmd[ACC_MSB],cmd[ACC_LSB]);
    DEBUG("CHRG_THH            [%X %X] \r\n",cmd[CHRG_THH_MSB],cmd[CHRG_THH_LSB]);
    DEBUG("CHRG_THL            [%X %X] \r\n",cmd[CHRG_THL_MSB],cmd[CHRG_THL_LSB]);
    DEBUG("VOLTAGE             [%X %X] \r\n",cmd[VOLT_MSB],cmd[VOLT_LSB]);
    DEBUG("VOLT_THH            [%X] \r\n",cmd[VOLT_THH]);    
    DEBUG("VOLT_THL            [%X] \r\n",cmd[VOLT_THL]);    
    DEBUG("TEMPERATURE         [%X %X] \r\n",cmd[TEMP_MSB],cmd[TEMP_LSB]);
    DEBUG("TEMPERATURE_THH     [%X] \r\n",cmd[TEMPERATURE_THH]);    
    DEBUG("TEMPERATURE_THL     [%X] \r\n",cmd[TEMPERATURE_THL]);    
    DEBUG("===================================================\r\n");
    DEBUG("\r\n");
}

int LTC29421::alertResponse(){
    char reg = getStatusReg();
    char ans;
    char cmd= 0x19;
    _i2c.read(cmd, &ans, 1);
    if(ans == 0xC8){
        DEBUG("alert = %x, reg = %x\r\n", ans,reg);
        return reg;
    }else
        return -1;
}

char LTC29421::getControlReg()
{
    char cmd;
    char ans;
    cmd= REG_CONTROL;
    _i2c.write(_addr, &cmd, 1, true);
    _i2c.read(_addr, &ans, 1);

    return ans;
}

char LTC29421::getStatusReg()
{
    char cmd;
    char ans;
    cmd= REG_STATUS;
    _i2c.write(_addr, &cmd, 1, true);
    _i2c.read(_addr, &ans, 1);

    return ans;
}

void LTC29421::setControlReg(char inp)
{
    char cmd[2];
    cmd[0] = REG_CONTROL;
    cmd[1] = inp;
    _i2c.write(_addr, cmd, 2, true);
}