u-blox / battery-charger-bq24295

Dependents:   example-battery-charger-bq24295 example-C030-out-of-box-demo example-C030-out-of-box-demo Amit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bq24295.cpp Source File

bq24295.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 u-blox
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /**
00018  * @file bq24295.cpp
00019  * This file defines the API to the TI BQ24295 battery charging chip.
00020  */
00021 
00022 // Define this to print debug information
00023 //#define DEBUG_BQ24295
00024 
00025 #include <mbed.h>
00026 #include <battery_charger_bq24295.h>
00027 
00028 #ifdef DEBUG_BQ24295
00029 # include <stdio.h>
00030 #endif
00031 
00032 /* ----------------------------------------------------------------
00033  * COMPILE-TIME MACROS
00034  * -------------------------------------------------------------- */
00035 
00036 /* ----------------------------------------------------------------
00037  * PRIVATE VARIABLES
00038  * -------------------------------------------------------------- */
00039 
00040 /* ----------------------------------------------------------------
00041  * GENERIC PRIVATE FUNCTIONS
00042  * -------------------------------------------------------------- */
00043 
00044 // Read from a register.
00045 bool BatteryChargerBq24295::getRegister(char address, char *pValue)
00046 {
00047     bool success = false;
00048 
00049     if (gpI2c != NULL) {
00050         // Move the address pointer
00051         if (gpI2c->write(gAddress, &address, 1) == 0) {
00052             if (pValue != NULL) {
00053                // Read from the address
00054                 if (gpI2c->read(gAddress, pValue, 1) == 0) {
00055                     success = true;
00056 #ifdef DEBUG_BQ24295
00057                     printf("BatteryChargerBq24295 (I2C 0x%02x): read 0x%02x from register 0x%02x.\r\n", gAddress >> 1, *pValue, address);
00058 #endif
00059                 }
00060             } else {
00061                 success = true;
00062             }
00063         }
00064     }
00065 
00066     return success;
00067 }
00068 
00069 // Write to a register.
00070 bool BatteryChargerBq24295::setRegister(char address, char value)
00071 {
00072     bool success = false;
00073     char data[2];
00074 
00075     if (gpI2c != NULL) {
00076         data[0] = address;
00077         data[1] = value;
00078         if (gpI2c->write(gAddress, &(data[0]), 2) == 0) {
00079             success = true;
00080 #ifdef DEBUG_BQ24295
00081             printf("BatteryChargerBq24295 (I2C 0x%02x): wrote 0x%02x to register 0x%02x.\r\n", gAddress >> 1, value, address);
00082 #endif
00083         }
00084     }
00085 
00086     return success;
00087 }
00088 
00089 // Set a mask of bits in a register.
00090 bool BatteryChargerBq24295::setRegisterBits(char address, char mask)
00091 {
00092     bool success = false;
00093     char value;
00094 
00095     if (getRegister(address, &value)) {
00096         value |= mask;
00097         if (setRegister(address, value)) {
00098             success = true;
00099         }
00100     }
00101 
00102     return success;
00103 }
00104 
00105 // Clear a mask of bits in a register.
00106 bool BatteryChargerBq24295::clearRegisterBits(char address, char mask)
00107 {
00108     bool success = false;
00109     char value;
00110 
00111     if (getRegister(address, &value)) {
00112         value &= ~mask;
00113         if (setRegister(address, value)) {
00114             success = true;
00115         }
00116     }
00117 
00118     return success;
00119 }
00120 
00121 /* ----------------------------------------------------------------
00122  * PUBLIC FUNCTIONS
00123  * -------------------------------------------------------------- */
00124 
00125 // Constructor.
00126 BatteryChargerBq24295::BatteryChargerBq24295(void)
00127 {
00128     gpI2c = NULL;
00129     gReady = false;
00130 }
00131 
00132 // Destructor.
00133 BatteryChargerBq24295::~BatteryChargerBq24295(void)
00134 {
00135 }
00136 
00137 // Initialise ourselves.
00138 bool BatteryChargerBq24295::init (I2C * pI2c, uint8_t address)
00139 {
00140     char reg;
00141 
00142     gpI2c = pI2c;
00143     gAddress = address << 1;
00144 
00145     if (gpI2c != NULL) {
00146         gpI2c->lock();
00147         
00148         // Read the revision status register
00149         if (getRegister(0x0a, &reg)) {
00150             // The expected response is 0xc0
00151             if (reg == 0xc0) {
00152                 gReady = true;
00153             }
00154         }
00155         gpI2c->unlock();
00156     }
00157 
00158 #ifdef DEBUG_BQ24295
00159     if (gReady) {
00160         printf("BatteryChargerBq24295 (I2C 0x%02x): handler initialised.\r\n", gAddress >> 1);
00161     } else {
00162         printf("BatteryChargerBq24295 (I2C 0x%02x): chip NOT initialised.\r\n", gAddress >> 1);
00163     }
00164 #endif
00165 
00166     return gReady;
00167 }
00168 
00169 // Get the charge state.
00170 BatteryChargerBq24295::ChargerState BatteryChargerBq24295::getChargerState(void)
00171 {
00172     BatteryChargerBq24295::ChargerState chargerState = CHARGER_STATE_UNKNOWN;
00173     char powerOnConfiguration;
00174     char systemStatus;
00175 
00176     if (gReady && (gpI2c != NULL)) {
00177         gpI2c->lock();
00178         // Read the power-on configuration register
00179         if (getRegister(0x01, &powerOnConfiguration)) {
00180             // Read the system status register
00181             if (getRegister(0x08, &systemStatus)) {
00182                 // Check the charge enable bit
00183                 if ((powerOnConfiguration & (1 << 4)) == 0) {
00184                     chargerState = CHARGER_STATE_DISABLED;
00185 #ifdef DEBUG_BQ24295
00186                     printf("BatteryChargerBq24295 (I2C 0x%02x): charging is disabled.\r\n", gAddress >> 1);
00187 #endif
00188                 } else {
00189                     // BatteryCharger is not disabled, so see if we have
00190                     // external power (bit 3)
00191                     if ((systemStatus & 0x04) == 0) {
00192                         chargerState = CHARGER_STATE_NO_EXTERNAL_POWER;
00193 #ifdef DEBUG_BQ24295
00194                         printf("BatteryChargerBq24295 (I2C 0x%02x): no external power.\r\n", gAddress >> 1);
00195 #endif
00196                     } else {
00197                         // Have power, so see how we're cooking (bits 4 & 5)
00198                         switch ((systemStatus >> 4) & 0x03) {
00199                             case 0:
00200                                 chargerState = CHARGER_STATE_NOT_CHARGING;
00201 #ifdef DEBUG_BQ24295
00202                                 printf("BatteryChargerBq24295 (I2C 0x%02x): not charging.\r\n", gAddress >> 1);
00203 #endif
00204                             break;
00205                             case 1:
00206                                 chargerState = CHARGER_STATE_PRECHARGE;
00207 #ifdef DEBUG_BQ24295
00208                                 printf("BatteryChargerBq24295 (I2C 0x%02x): pre-charge.\r\n", gAddress >> 1);
00209 #endif
00210                             break;
00211                             case 2:
00212                                 chargerState = CHARGER_STATE_FAST_CHARGE;
00213 #ifdef DEBUG_BQ24295
00214                                 printf("BatteryChargerBq24295 (I2C 0x%02x): fast charge.\r\n", gAddress >> 1);
00215 #endif
00216                             break;
00217                             case 3:
00218                                 chargerState = CHARGER_STATE_COMPLETE;
00219 #ifdef DEBUG_BQ24295
00220                                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging complete.\r\n", gAddress >> 1);
00221 #endif
00222                             break;
00223                             default:
00224                             break;
00225                         }
00226                     }
00227                 }
00228             }
00229         }
00230         gpI2c->unlock();
00231     }
00232 
00233     return chargerState;
00234 }
00235 
00236 // Get whether external power is present or not.
00237 bool BatteryChargerBq24295::isExternalPowerPresent(void)
00238 {
00239     bool isPresent = false;
00240     char reg;
00241 
00242     if (gReady && (gpI2c != NULL)) {
00243         gpI2c->lock();
00244         // Read the system status register
00245         if (getRegister(0x08, &reg)) {
00246            // See if we have external power (bit 3)
00247             if ((reg & 0x04) != 0) {
00248                 isPresent = true;
00249             }
00250 
00251 #ifdef DEBUG_BQ24295
00252             if (isPresent) {
00253                 printf("BatteryChargerBq24295 (I2C 0x%02x): external power is present.\r\n", gAddress >> 1);
00254             } else {
00255                 printf("BatteryChargerBq24295 (I2C 0x%02x): external power is NOT present.\r\n", gAddress >> 1);
00256             }
00257 #endif
00258         }
00259         gpI2c->unlock();
00260     }
00261 
00262     return isPresent;
00263 }
00264 
00265 // Enable charging.
00266 bool BatteryChargerBq24295::enableCharging (void)
00267 {
00268     bool success = false;
00269 
00270     if (gReady && (gpI2c != NULL)) {
00271         gpI2c->lock();
00272         // Charge enable is bit 4 of the power-on configuration register
00273         success = setRegisterBits(0x01, (1 << 4));
00274 #ifdef DEBUG_BQ24295
00275         if (success) {
00276             printf("BatteryChargerBq24295 (I2C 0x%02x): charging now ENABLED.\r\n", gAddress >> 1);
00277         }
00278 #endif
00279         gpI2c->unlock();
00280     }
00281     
00282     return success;
00283 }
00284 
00285 // Disable charging.
00286 bool BatteryChargerBq24295::disableCharging (void)
00287 {
00288     bool success = false;
00289     
00290     if (gReady && (gpI2c != NULL)) {
00291         gpI2c->lock();
00292         // Charge enable is bit 4 of the power-on configuration register
00293         success = clearRegisterBits(0x01, (1 << 4));
00294 #ifdef DEBUG_BQ24295
00295         if (success) {
00296             printf("BatteryChargerBq24295 (I2C 0x%02x): charging now DISABLED.\r\n", gAddress >> 1);
00297         }
00298 #endif
00299         gpI2c->unlock();
00300     }
00301     
00302     return success;
00303 }
00304 
00305 // Get the whether charging is enabled or disabled.
00306 bool BatteryChargerBq24295::isChargingEnabled (void)
00307 {
00308     bool isEnabled = false;
00309     char reg;
00310     
00311     if (gReady && (gpI2c != NULL)) {
00312         gpI2c->lock();
00313         // Read the power-on configuration register
00314         if (getRegister(0x01, &reg)) {
00315             // Charge enable is bit 4 of the power-on configuration register
00316             if ((reg & (1 << 4)) != 0) {
00317                 isEnabled = true;
00318             }
00319 #ifdef DEBUG_BQ24295
00320             if (isEnabled) {
00321                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging is ENABLED.\r\n", gAddress >> 1);
00322             } else {
00323                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging is DISABLED.\r\n", gAddress >> 1);
00324             }
00325 #endif
00326         }
00327         gpI2c->unlock();
00328     }
00329     
00330     return isEnabled;
00331 }
00332 
00333 // Enable OTG charging.
00334 bool BatteryChargerBq24295::enableOtg (void)
00335 {
00336     bool success = false;
00337 
00338     if (gReady && (gpI2c != NULL)) {
00339         gpI2c->lock();
00340         // OTG enable is bit 5 of the power-on configuration register
00341         success = setRegisterBits(0x01, (1 << 5));
00342 #ifdef DEBUG_BQ24295
00343         if (success) {
00344             printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging now ENABLED.\r\n", gAddress >> 1);
00345         }
00346 #endif
00347         gpI2c->unlock();
00348     }
00349     
00350     return success;
00351 }
00352 
00353 // Disable OTG charging.
00354 bool BatteryChargerBq24295::disableOtg (void)
00355 {
00356     bool success = false;
00357 
00358     if (gReady && (gpI2c != NULL)) {
00359         gpI2c->lock();
00360         // OTG enable is bit 5 of the power-on configuration register
00361         success = clearRegisterBits(0x01, (1 << 5));
00362 #ifdef DEBUG_BQ24295
00363         if (success) {
00364             printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging now DISABLED.\r\n", gAddress >> 1);
00365         }
00366 #endif
00367         gpI2c->unlock();
00368     }
00369     
00370     return success;
00371 }
00372 
00373 // Get whether OTG charging is enabled or not.
00374 bool BatteryChargerBq24295::isOtgEnabled (void)
00375 {
00376     bool isEnabled = false;
00377     char reg;
00378     
00379     if (gReady && (gpI2c != NULL)) {
00380         gpI2c->lock();
00381         // Read the power-on configuration register
00382         if (getRegister(0x01, &reg)) {
00383             // OTG enable is bit 5 of the power-on configuration register
00384             if ((reg & (1 << 5)) != 0) {
00385                 isEnabled = true;
00386             }
00387 #ifdef DEBUG_BQ24295
00388             if (isEnabled) {
00389                 printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging is ENABLED.\r\n", gAddress >> 1);
00390             } else {
00391                 printf("BatteryChargerBq24295 (I2C 0x%02x): OTG charging is DISABLED.\r\n", gAddress >> 1);
00392             }
00393 #endif
00394         }
00395         gpI2c->unlock();
00396     }
00397     
00398     return isEnabled;
00399 }
00400 
00401 // Set the system voltage.
00402 bool BatteryChargerBq24295::setSystemVoltage (int32_t voltageMV)
00403 {
00404     bool success = false;
00405     char reg;
00406     int32_t codedValue;
00407 
00408     if (gReady && (gpI2c != NULL)) {
00409         gpI2c->lock();
00410         // Read the power-on configuration register
00411         if (getRegister(0x01, &reg)) {
00412             // System voltage is in bits 1 to 3,
00413             // coded to base "100 mV" with
00414             // an offset of 3000 mV.
00415             if ((voltageMV >= 3000) && (voltageMV <= 3700)) {
00416                 codedValue = voltageMV;
00417                 codedValue = (codedValue - 3000) / 100;
00418                 // If the voltage minus the base is not an exact multiple of 100,
00419                 // add one to the coded value to make sure we don't
00420                 // go under the requested system voltage
00421                 if ((voltageMV - 3000) % 100 != 0) {
00422                     codedValue++;
00423                 }
00424                 
00425                 reg &= ~(0x07 << 1);
00426                 reg |= (char) ((codedValue & 0x07) << 1);
00427                 
00428                 // Write to the power-on configuration register
00429                 success = setRegister (0x01, reg);
00430 #ifdef DEBUG_BQ24295
00431                 if (success) {
00432                     printf("BatteryChargerBq24295 (I2C 0x%02x): system voltage now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000);
00433                 }
00434 #endif
00435             }
00436         }
00437         gpI2c->unlock();
00438     }
00439 
00440     return success;
00441 }
00442 
00443 // Get the system voltage.
00444 bool BatteryChargerBq24295::getSystemVoltage (int32_t *pVoltageMV)
00445 {
00446     bool success = false;
00447     char reg;
00448 
00449     if (gReady && (gpI2c != NULL)) {
00450         gpI2c->lock();
00451         // Read the power-on configuration register
00452         if (getRegister(0x01, &reg)) {
00453             success = true;
00454             if (pVoltageMV != NULL) {
00455                 // Input voltage limit is in bits 1 to 3
00456                 // Base voltage
00457                 *pVoltageMV = 3000;
00458                 // Shift reg down and add the number of multiples
00459                 // of 100 mV
00460                 reg = (reg >> 1) & 0x07;
00461                 *pVoltageMV += ((int32_t) reg) * 100;
00462 #ifdef DEBUG_BQ24295
00463                 printf("BatteryChargerBq24295 (I2C 0x%02x): system voltage is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000);
00464 #endif
00465             }
00466         }
00467         gpI2c->unlock();
00468     }
00469 
00470     return success;
00471 }
00472 
00473 // Set the fast charging current limit.
00474 bool BatteryChargerBq24295::setFastChargingCurrentLimit (int32_t currentMA)
00475 {
00476     bool success = false;
00477     char reg;
00478     int32_t codedValue;
00479 
00480     if (gReady && (gpI2c != NULL)) {
00481         gpI2c->lock();
00482         // Read the charge current control register
00483         if (getRegister(0x02, &reg)) {
00484             // Fast charging current limit is in
00485             // bits 2 to 7, coded to base "64 mA" with
00486             // an offset of 512 mA.
00487             if ((currentMA >= 512) && (currentMA <= 3008)) {
00488                 codedValue = currentMA;
00489                 codedValue = (codedValue - 512) / 64;
00490                 
00491                 reg &= ~(0x3f << 2);
00492                 reg |= (char) ((codedValue & 0x3f) << 2);
00493 
00494                 // Write to the charge current control register
00495                 success = setRegister (0x02, reg);
00496 #ifdef DEBUG_BQ24295
00497                 if (success) {
00498                     printf("BatteryChargerBq24295 (I2C 0x%02x): fast charging current limit now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000);
00499                 }
00500 #endif
00501             }
00502         }
00503         gpI2c->unlock();
00504     }
00505 
00506     return success;
00507 }
00508 
00509 // Get the fast charging current limit.
00510 bool BatteryChargerBq24295::getFastChargingCurrentLimit (int32_t *pCurrentMA)
00511 {
00512     bool success = false;
00513     char reg;
00514 
00515     if (gReady && (gpI2c != NULL)) {
00516         gpI2c->lock();
00517         // Read the charge current control register
00518         if (getRegister(0x02, &reg)) {
00519             success = true;
00520             if (pCurrentMA != NULL) {
00521                 // Fast charging current limit is in bits 2 to 7
00522                 // Base current
00523                 *pCurrentMA = 512;
00524                 // Shift reg down and add the number of multiples
00525                 // of 64 mA
00526                 reg = (reg >> 2) & 0x3f;
00527                 *pCurrentMA += ((int32_t) reg) * 64;
00528 #ifdef DEBUG_BQ24295
00529                 printf("BatteryChargerBq24295 (I2C 0x%02x): fast charge current limit is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000);
00530 #endif
00531             }
00532         }
00533         gpI2c->unlock();
00534     }
00535 
00536     return success;
00537 }
00538 
00539 // Enable the ICHG/IPRECH margin.
00540 bool BatteryChargerBq24295::enableIcghIprechMargin (void)
00541 {
00542     bool success = false;
00543 
00544     if (gReady && (gpI2c != NULL)) {
00545         gpI2c->lock();
00546         // FORCE_20PCT is bit 0 of the charge current control register
00547         success = setRegisterBits(0x02, (1 << 0));
00548 #ifdef DEBUG_BQ24295
00549         if (success) {
00550             printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin now ENABLED.\r\n", gAddress >> 1);
00551         }
00552 #endif
00553         gpI2c->unlock();
00554     }
00555 
00556     return success;
00557 }
00558 
00559 // Disable the ICHG/IPRECH margin.
00560 bool BatteryChargerBq24295::disableIcghIprechMargin (void)
00561 {
00562     bool success = false;
00563 
00564     if (gReady && (gpI2c != NULL)) {
00565         gpI2c->lock();
00566         // FORCE_20PCT is bit 0 of the charge current control register
00567         success = clearRegisterBits(0x02, (1 << 0));
00568 #ifdef DEBUG_BQ24295
00569         if (success) {
00570             printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin now DISABLED.\r\n", gAddress >> 1);
00571         }
00572 #endif
00573         gpI2c->unlock();
00574     }
00575 
00576     return success;
00577 }
00578 
00579 // Check if the ICHG/IPRECH margin is set.
00580 bool BatteryChargerBq24295::isIcghIprechMarginEnabled (void)
00581 {
00582     bool isEnabled = false;
00583     char reg;
00584     
00585     if (gReady && (gpI2c != NULL)) {
00586         gpI2c->lock();
00587         // Read the charge current control register
00588         if (getRegister(0x02, &reg)) {
00589             // FORCE_20PCT is bit 0
00590             if ((reg & (1 << 0)) != 0) {
00591                 isEnabled = true;
00592             }
00593 #ifdef DEBUG_BQ24295
00594             if (isEnabled) {
00595                 printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin is ENABLED.\r\n", gAddress >> 1);
00596             } else {
00597                 printf("BatteryChargerBq24295 (I2C 0x%02x): ICGH/IPRECH margin is DISABLED.\r\n", gAddress >> 1);
00598             }
00599 #endif
00600         }
00601         gpI2c->unlock();
00602     }
00603 
00604     return isEnabled;
00605 }
00606     
00607 // Set the fast charging safety timer.
00608 bool BatteryChargerBq24295::setFastChargingSafetyTimer (int32_t timerHours)
00609 {
00610     bool success = false;
00611     char reg;
00612     int32_t codedValue;
00613 
00614     if (gReady && (gpI2c != NULL)) {
00615         gpI2c->lock();
00616         // Mustn't be silly
00617         if (timerHours >= 0) {
00618             // Read the charge termination/timer control register
00619             if (getRegister(0x05, &reg)) {
00620                 // Timer setting is in bits 1 & 2, enable is in bit 3
00621                 if (timerHours == 0) {
00622                     reg &= ~(1 << 3);
00623                 } else {
00624                     reg |= (1 << 3);
00625                     if (timerHours < 8) {
00626                         codedValue = 0;
00627                     } else if (timerHours < 12) {
00628                         codedValue = 1;
00629                     } else if (timerHours < 20) {
00630                         codedValue = 2;
00631                     } else {
00632                         codedValue = 3;
00633                     }
00634                     reg &= ~(0x03 << 1);
00635                     reg |= (char) (codedValue << 1);
00636                 }
00637                 // Write to the charge termination/timer control register
00638                 success = setRegister (0x05, reg);
00639 #ifdef DEBUG_BQ24295
00640                 if (success) {
00641                     printf("BatteryChargerBq24295 (I2C 0x%02x): fast charging safety timer now set to %d hours.\r\n", gAddress >> 1, (int) timerHours);
00642                 }
00643 #endif
00644             }
00645         }
00646         gpI2c->unlock();
00647     }
00648 
00649     return success;
00650 }
00651 
00652 // Get the value of the fast charging safety timer.
00653 bool BatteryChargerBq24295::getFastChargingSafetyTimer (int32_t *pTimerHours)
00654 {
00655     bool success = false;
00656     char reg;
00657 
00658     if (gReady && (gpI2c != NULL)) {
00659         gpI2c->lock();
00660         // Read the charge termination/timer control register
00661         if (getRegister(0x05, &reg)) {
00662             success = true;
00663             if (pTimerHours != NULL) {
00664                 *pTimerHours = 0;
00665                 // Timer enable is in bit 3
00666                 if ((reg & (1 << 3)) != 0) {
00667                     // Timer value is in bits 1 & 2
00668                     switch ((reg >> 1) & 0x03) {
00669                         case 0:
00670                             *pTimerHours = 5;
00671                         break;
00672                         case 1:
00673                             *pTimerHours = 8;
00674                         break;
00675                         case 2:
00676                             *pTimerHours = 12;
00677                         break;
00678                         case 3:
00679                             *pTimerHours = 20;
00680                         break;
00681                         default:
00682                             MBED_ASSERT(false);
00683                         break;
00684                     }
00685                 }
00686 #ifdef DEBUG_BQ24295
00687                 printf("BatteryChargerBq24295 (I2C 0x%02x): fast charging safety timer is %d hours.\r\n", gAddress >> 1, (int) *pTimerHours);
00688 #endif
00689             }
00690         }
00691         gpI2c->unlock();
00692     }
00693 
00694     return success;
00695 }
00696 
00697 // Set the charging termination current.
00698 bool BatteryChargerBq24295::setChargingTerminationCurrent (int32_t currentMA)
00699 {
00700     bool success = false;
00701     char reg;
00702     int32_t codedValue;
00703 
00704     if (gReady && (gpI2c != NULL)) {
00705         gpI2c->lock();
00706         // Read the pre-charge/termination current control register
00707         if (getRegister(0x03, &reg)) {
00708             // Charging termination current limit is in
00709             // bits 0 to 3, coded to base "128 mA" with
00710             // an offset of 128 mA.
00711             if ((currentMA >= 128) && (currentMA <= 2048)) {
00712                 codedValue = currentMA;
00713                 codedValue = (codedValue - 128) / 128;
00714                 
00715                 reg &= ~0x0f;
00716                 reg |= (char) (codedValue & 0x0f);
00717 
00718                 // Write to the pre-charge/termination current control register
00719                 success = setRegister (0x03, reg);
00720 #ifdef DEBUG_BQ24295
00721                 if (success) {
00722                     printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination current now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000);
00723                 }
00724 #endif
00725             }
00726         }
00727         gpI2c->unlock();
00728     }
00729 
00730     return success;
00731 }
00732 
00733 // Get the charging termination current.
00734 bool BatteryChargerBq24295::getChargingTerminationCurrent (int32_t *pCurrentMA)
00735 {
00736     bool success = false;
00737     char reg;
00738 
00739     if (gReady && (gpI2c != NULL)) {
00740         gpI2c->lock();
00741         // Read the pre-charge/termination current control register
00742         if (getRegister(0x03, &reg)) {
00743             success = true;
00744             if (pCurrentMA != NULL) {
00745                 // Pre-charging current limit is in bits 0 to 3
00746                 // Base current
00747                 *pCurrentMA = 128;
00748                 // Add the number of multiples of 128 mA
00749                 reg = reg & 0x0f;
00750                 *pCurrentMA += ((int32_t) reg) * 128;
00751 #ifdef DEBUG_BQ24295
00752                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination current is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000);
00753 #endif
00754             }
00755         }
00756         gpI2c->unlock();
00757     }
00758 
00759     return success;
00760 }
00761 
00762 // Enable charging termination.
00763 bool BatteryChargerBq24295::enableChargingTermination (void)
00764 {
00765     bool success = false;
00766 
00767     if (gReady && (gpI2c != NULL)) {
00768         gpI2c->lock();
00769         // EN_TERM is bit 7 of the charge termination/timer control register
00770         success = setRegisterBits(0x05, (1 << 7));
00771 #ifdef DEBUG_BQ24295
00772         if (success) {
00773             printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination now ENABLED.\r\n", gAddress >> 1);
00774         }
00775 #endif
00776         gpI2c->unlock();
00777     }
00778 
00779     return success;
00780 }
00781 
00782 // Disable charging termination.
00783 bool BatteryChargerBq24295::disableChargingTermination (void)
00784 {
00785     bool success = false;
00786 
00787     if (gReady && (gpI2c != NULL)) {
00788         gpI2c->lock();
00789         // EN_TERM is bit 7 of the charge termination/timer control register
00790         success = clearRegisterBits(0x05, (1 << 7));
00791 #ifdef DEBUG_BQ24295
00792         if (success) {
00793             printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination now DISABLED.\r\n", gAddress >> 1);
00794         }
00795 #endif
00796         gpI2c->unlock();
00797     }
00798 
00799     return success;
00800 }
00801 
00802 // Get the state of charging termination (enabled or disabled)
00803 bool BatteryChargerBq24295::isChargingTerminationEnabled (void)
00804 {
00805     bool isEnabled = false;
00806     char reg;
00807     
00808     if (gReady && (gpI2c != NULL)) {
00809         gpI2c->lock();
00810         // Read the charge termination/timer control register
00811         if (getRegister(0x05, &reg)) {
00812             // EN_TERM is bit 7
00813             if ((reg & (1 << 7)) != 0) {
00814                 isEnabled = true;
00815             }
00816 #ifdef DEBUG_BQ24295
00817             if (isEnabled) {
00818                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination is ENABLED.\r\n", gAddress >> 1);
00819             } else {
00820                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging termination is DISABLED.\r\n", gAddress >> 1);
00821             }
00822 #endif
00823         }
00824         gpI2c->unlock();
00825     }
00826 
00827     return isEnabled;
00828 }
00829 
00830 // Set the pre-charging current limit.
00831 bool BatteryChargerBq24295::setPrechargingCurrentLimit (int32_t currentMA)
00832 {
00833     bool success = false;
00834     char reg;
00835     int32_t codedValue;
00836 
00837     if (gReady && (gpI2c != NULL)) {
00838         gpI2c->lock();
00839         // Read the pre-charge/termination current control register
00840         if (getRegister(0x03, &reg)) {
00841             // Pre-charging current limit is in
00842             // bits 4 to 7, coded to base "128 mA" with
00843             // an offset of 128 mA.
00844             if ((currentMA >= 128) && (currentMA <= 2048)) {
00845                 codedValue = currentMA;
00846                 codedValue = (codedValue - 128) / 128;
00847                 
00848                 reg &= ~(0x0f << 4);
00849                 reg |= (char) ((codedValue & 0x0f) << 4);
00850 
00851                 // Write to the pre-charge/termination current control register
00852                 success = setRegister (0x03, reg);
00853 #ifdef DEBUG_BQ24295
00854                 if (success) {
00855                     printf("BatteryChargerBq24295 (I2C 0x%02x): pre-charging current limit now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000);
00856                 }
00857 #endif
00858             }
00859         }
00860         gpI2c->unlock();
00861     }
00862 
00863     return success;
00864 }
00865 
00866 // Get the pre-charging current limit.
00867 bool BatteryChargerBq24295::getPrechargingCurrentLimit (int32_t *pCurrentMA)
00868 {
00869     bool success = false;
00870     char reg;
00871 
00872     if (gReady && (gpI2c != NULL)) {
00873         gpI2c->lock();
00874         // Read the pre-charge/termination current control register
00875         if (getRegister(0x03, &reg)) {
00876             success = true;
00877             if (pCurrentMA != NULL) {
00878                 // Pre-charging current limit is in bits 4 to 7
00879                 // Base current
00880                 *pCurrentMA = 128;
00881                 // Shift reg down and add the number of multiples
00882                 // of 128 mA
00883                 reg = (reg >> 4) & 0x0f;
00884                 *pCurrentMA += ((int32_t) reg) * 128;
00885 #ifdef DEBUG_BQ24295
00886                 printf("BatteryChargerBq24295 (I2C 0x%02x): pre-charging current limit is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000);
00887 #endif
00888             }
00889         }
00890         gpI2c->unlock();
00891     }
00892 
00893     return success;
00894 }
00895 
00896 // Set the charging voltage limit.
00897 bool BatteryChargerBq24295::setChargingVoltageLimit (int32_t voltageMV)
00898 {
00899     bool success = false;
00900     char reg;
00901     int32_t codedLimit;
00902 
00903     if (gReady && (gpI2c != NULL)) {
00904         gpI2c->lock();
00905         // Read the charging voltage control register
00906         if (getRegister(0x04, &reg)) {
00907             // Charging voltage limit is in bits 2 to 7
00908             // but it is coded to base "16 mV" with
00909             // an offset of 3504 mV.
00910             if ((voltageMV >= 3504) && (voltageMV <= 4400)) {
00911                 codedLimit = voltageMV;
00912                 codedLimit = (codedLimit - 3504) / 16;
00913                 
00914                 reg &= ~(0x3f << 2);
00915                 reg |= (char) ((codedLimit & 0x3f) << 2);
00916                 
00917                // Write to the charging voltage control register
00918                 success = setRegister (0x04, reg);
00919 #ifdef DEBUG_BQ24295
00920                 if (success) {
00921                     printf("BatteryChargerBq24295 (I2C 0x%02x): charging voltage limit now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000);
00922                 }
00923 #endif
00924             }
00925         }
00926         gpI2c->unlock();
00927     }
00928 
00929     return success;
00930 }
00931 
00932 // Get the charging voltage limit.
00933 bool BatteryChargerBq24295::getChargingVoltageLimit (int32_t *pVoltageMV)
00934 {
00935     bool success = false;
00936     char reg;
00937 
00938     if (gReady && (gpI2c != NULL)) {
00939         gpI2c->lock();
00940         // Read the charging voltage control register
00941         if (getRegister(0x04, &reg)) {
00942             success = true;
00943             if (pVoltageMV != NULL) {
00944                 // Charging voltage limit is in bits 2 to 7
00945                 // Base voltage
00946                 *pVoltageMV = 3504;
00947                 // Shift reg down and add the number of multiples
00948                 // of 16 mV
00949                 reg = (reg >> 2) & 0x3f;
00950                 *pVoltageMV += ((int32_t) reg) * 16;
00951 #ifdef DEBUG_BQ24295
00952                 printf("BatteryChargerBq24295 (I2C 0x%02x): charging voltage limit is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000);
00953 #endif
00954             }
00955         }
00956         gpI2c->unlock();
00957     }
00958 
00959     return success;
00960 }
00961 
00962 // Set the pre-charge to fast-charge voltage threshold.
00963 bool BatteryChargerBq24295::setFastChargingVoltageThreshold (int32_t voltageMV)
00964 {
00965     bool success = false;
00966 
00967     if (gReady && (gpI2c != NULL)) {
00968         gpI2c->lock();
00969         // There are only two possible values, 2.8 V and 3.0 V.
00970         // BATLOWV is bit 1 of the charging voltage control register
00971         if (voltageMV > 2800) {
00972             success = setRegisterBits(0x04, (1 << 1));
00973 #ifdef DEBUG_BQ24295
00974             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 3.000 V.\r\n", gAddress >> 1);
00975 #endif
00976         } else {
00977             success = clearRegisterBits(0x04, (1 << 1));
00978 #ifdef DEBUG_BQ24295
00979             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 2.800 V.\r\n", gAddress >> 1);
00980 #endif
00981         }
00982         gpI2c->unlock();
00983     }
00984 
00985     return success;
00986 }
00987 
00988 // Get the pre-charge to fast-charge voltage threshold.
00989 bool BatteryChargerBq24295::getFastChargingVoltageThreshold (int32_t *pVoltageMV)
00990 {
00991     bool success = false;
00992     char reg;
00993 
00994     if (gReady && (gpI2c != NULL)) {
00995         gpI2c->lock();
00996         // BATLOWV is bit 1 of the charging voltage control register
00997         if (getRegister(0x04, &reg)) {
00998             success = true;
00999             if (pVoltageMV != NULL) {
01000                 *pVoltageMV = 2800;
01001                 if ((reg & (1 << 1)) != 0) {
01002                     *pVoltageMV = 3000;
01003                 }
01004             }
01005         }
01006         
01007 #ifdef DEBUG_BQ24295
01008         if (reg & (1 << 1)) {
01009             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 3.000 V.\r\n", gAddress >> 1);
01010         } else {
01011             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 2.800 V.\r\n", gAddress >> 1);
01012         }
01013 #endif
01014         gpI2c->unlock();
01015     }
01016 
01017     return success;
01018 }
01019 
01020 // Set the recharging voltage threshold.
01021 bool BatteryChargerBq24295::setRechargingVoltageThreshold (int32_t voltageMV)
01022 {
01023     bool success = false;
01024 
01025     if (gReady && (gpI2c != NULL)) {
01026         gpI2c->lock();
01027         // There are only two possible values, 100 mV and 300 mV.
01028         // VRECHG is bit 0 of the charging voltage control register
01029         if (voltageMV > 100) {
01030             success = setRegisterBits(0x04, (1 << 0));
01031 #ifdef DEBUG_BQ24295
01032             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 0.300 V.\r\n", gAddress >> 1);
01033 #endif
01034         } else {
01035             success = clearRegisterBits(0x04, (1 << 0));
01036 #ifdef DEBUG_BQ24295
01037             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold now set to 0.100 V.\r\n", gAddress >> 1);
01038 #endif
01039         }
01040         gpI2c->unlock();
01041     }
01042 
01043     return success;
01044 }
01045 
01046 // Get the recharging voltage threshold.
01047 bool BatteryChargerBq24295::getRechargingVoltageThreshold (int32_t *pVoltageMV)
01048 {
01049     bool success = false;
01050     char reg;
01051 
01052     if (gReady && (gpI2c != NULL)) {
01053         gpI2c->lock();
01054         // VRECHG is bit 0 of the charging voltage control register
01055         if (getRegister(0x04, &reg)) {
01056             success = true;
01057             if (pVoltageMV != NULL) {
01058                 *pVoltageMV = 100;
01059                 if ((reg & (1 << 0)) != 0) {
01060                     *pVoltageMV = 300;
01061                 }
01062             }
01063         }
01064         
01065 #ifdef DEBUG_BQ24295
01066         if (reg & (1 << 1)) {
01067             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 0.300 V.\r\n", gAddress >> 1);
01068         } else {
01069             printf("BatteryChargerBq24295 (I2C 0x%02x): recharge voltage threshold is 0.100 V.\r\n", gAddress >> 1);
01070         }
01071 #endif
01072         gpI2c->unlock();
01073     }
01074 
01075     return success;
01076 }
01077 
01078 // Set the boost voltage.
01079 bool BatteryChargerBq24295::setBoostVoltage (int32_t voltageMV)
01080 {
01081     bool success = false;
01082     char reg;
01083     int32_t codedValue;
01084 
01085     if (gReady && (gpI2c != NULL)) {
01086         gpI2c->lock();
01087         // Read the boost voltage/thermal regulation control register
01088         if (getRegister(0x06, &reg)) {
01089             // Boost voltage is in bits 4 to 7, coded to base "64 mV"
01090             // with an offset of 4550 mV.
01091             if ((voltageMV >= 4550) && (voltageMV <= 5510)) {
01092                 codedValue = voltageMV;
01093                 codedValue = (codedValue - 4550) / 64;
01094                 // If the voltage minus the base is not an exact multiple of 64,
01095                 // add one to the coded value to make sure we don't
01096                 // go under the requested boost voltage
01097                 if ((voltageMV - 4550) % 64 != 0) {
01098                     codedValue++;
01099                 }
01100                 
01101                 reg &= ~(0x0f << 4);
01102                 reg |= (char) ((codedValue & 0x0f) << 4);
01103                 
01104                 // Write to the boost voltage/thermal regulation control register
01105                 success = setRegister (0x06, reg);
01106 #ifdef DEBUG_BQ24295
01107                 if (success) {
01108                     printf("BatteryChargerBq24295 (I2C 0x%02x): boost voltage now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000);
01109                 }
01110 #endif
01111             }
01112         }
01113         gpI2c->unlock();
01114     }
01115     
01116     return success;
01117 }
01118 
01119 // Get the boost voltage.
01120 bool BatteryChargerBq24295::getBoostVoltage (int32_t *pVoltageMV)
01121 {
01122     bool success = false;
01123     char reg;
01124 
01125     if (gReady && (gpI2c != NULL)) {
01126         gpI2c->lock();
01127         // Read the boost voltage/thermal regulation control register
01128         if (getRegister(0x06, &reg)) {
01129             success = true;
01130             if (pVoltageMV != NULL) {
01131                 // Boost voltage is in bits 4 to 7
01132                 // Base voltage
01133                 *pVoltageMV = 4550;
01134                 // Shift reg down and add the number of multiples
01135                 // of 64 mV
01136                 reg = (reg >> 4) & 0x0f;
01137                 *pVoltageMV += ((int32_t) reg) * 64;
01138 #ifdef DEBUG_BQ24295
01139                 printf("BatteryChargerBq24295 (I2C 0x%02x): boost voltage is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000);
01140 #endif
01141             }
01142         }
01143         gpI2c->unlock();
01144     }
01145 
01146     return success;
01147 }
01148 
01149 // Set the boost mode low temperature limit.
01150 bool BatteryChargerBq24295::setBoostUpperTemperatureLimit (int32_t temperatureC)
01151 {
01152     bool success = false;
01153     char reg;
01154     char codedValue;
01155 
01156     if (gReady && (gpI2c != NULL)) {
01157         gpI2c->lock();
01158         // Read the boost voltage/thermal regulation control register
01159         if (getRegister(0x06, &reg)) {
01160             // BHOT is in bits 2 & 3
01161             if (temperatureC < 60) {
01162                 codedValue = 0;
01163             } else if (temperatureC < 65) {
01164                 codedValue = 1;
01165             } else {
01166                 codedValue = 2;
01167             }
01168             reg &= ~(0x03 << 2);
01169             reg |= (char) (codedValue << 2);
01170             // Write to boost voltage/thermal regulation control register
01171             success = setRegister (0x06, reg);
01172 #ifdef DEBUG_BQ24295
01173             if (success) {
01174                 printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit now set to %d C.\r\n", gAddress >> 1, (int) temperatureC);
01175             }
01176 #endif
01177         }
01178         gpI2c->unlock();
01179     }
01180 
01181     return success;
01182 }
01183 
01184 // Get the boost mode upper temperature limit.
01185 bool BatteryChargerBq24295::getBoostUpperTemperatureLimit (int32_t *pTemperatureC)
01186 {
01187     bool success = false;
01188     char reg;
01189 
01190     if (gReady && (gpI2c != NULL)) {
01191         gpI2c->lock();
01192         // BHOT is in bits 2 & 3 of the boost voltage/thermal regulation control register
01193         if (getRegister(0x06, &reg)) {
01194             // Only proceed (and return true) if the limit is enabled
01195             if (((reg >> 2) & 0x03) != 0x03) {
01196                 success = true;
01197                 if (pTemperatureC != NULL) {
01198                     switch ((reg >> 2) & 0x03) {
01199                         case 0:
01200                             *pTemperatureC = 55;
01201                         break;
01202                         case 1:
01203                             *pTemperatureC = 60;
01204                         break;
01205                         case 2:
01206                             *pTemperatureC = 65;
01207                         break;
01208                         default:
01209                             MBED_ASSERT(false);
01210                         break;
01211                     }
01212 #ifdef DEBUG_BQ24295
01213                     printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit is %d C.\r\n", gAddress >> 1, (int) *pTemperatureC);
01214 #endif
01215                 }
01216             }
01217         }
01218         gpI2c->unlock();
01219     }
01220 
01221     return success;
01222 }
01223     
01224 // Check whether the boost mode upper temperature limit is enabled.
01225 bool BatteryChargerBq24295::isBoostUpperTemperatureLimitEnabled (void)
01226 {
01227     bool isEnabled = false;
01228     char reg;
01229     
01230     if (gReady && (gpI2c != NULL)) {
01231         gpI2c->lock();
01232         // BHOT is in bits 2 & 3 of the boost voltage/thermal regulation control register
01233         // and it is enabled if any bit is 0
01234         if (getRegister(0x06, &reg)) {
01235             if (((reg >> 2) & 3) != 3) {
01236                 isEnabled = true;
01237             }
01238 #ifdef DEBUG_BQ24295
01239             if (isEnabled) {
01240                 printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit is ENABLED.\r\n", gAddress >> 1);
01241             } else {
01242                 printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit is DISABLED.\r\n", gAddress >> 1);
01243             }
01244 #endif
01245         }
01246         gpI2c->unlock();
01247     }
01248 
01249     return isEnabled;
01250 }
01251 
01252 // Disable the boost mode upper temperature limit.
01253 bool BatteryChargerBq24295::disableBoostUpperTemperatureLimit (void)
01254 {
01255     bool success = false;
01256 
01257     if (gReady && (gpI2c != NULL)) {
01258         gpI2c->lock();
01259         // BHOT is in bits 2 & 3 of the boost voltage/thermal regulation control register
01260         // and setting all the bits indicates disabled
01261         success = setRegisterBits(0x06, (3 << 2));
01262 #ifdef DEBUG_BQ24295
01263         if (success) {
01264             printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode upper temperature limit now DISABLED.\r\n", gAddress >> 1);
01265         }
01266 #endif
01267         gpI2c->unlock();
01268     }
01269 
01270     return success;
01271 }
01272 
01273 // Set the boost mode upper temperature limit.
01274 bool BatteryChargerBq24295::setBoostLowerTemperatureLimit (int32_t temperatureC)
01275 {
01276     bool success = false;
01277 
01278     if (gReady && (gpI2c != NULL)) {
01279         gpI2c->lock();
01280         // There are only two possible values, -10 C and -20 C.
01281         // BCOLD is bit 1 of the charge current control register
01282         if (temperatureC < -10) {
01283             success = setRegisterBits(0x02, (1 << 1));
01284 #ifdef DEBUG_BQ24295
01285             printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit now set to -20 C.\r\n", gAddress >> 1);
01286 #endif
01287         } else {
01288             success = clearRegisterBits(0x02, (1 << 1));
01289 #ifdef DEBUG_BQ24295
01290             printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit now set to -10 C.\r\n", gAddress >> 1);
01291 #endif
01292         }
01293         gpI2c->unlock();
01294     }
01295 
01296     return success;
01297 }
01298 
01299 // Get the boost mode low temperature limit.
01300 bool BatteryChargerBq24295::getBoostLowerTemperatureLimit (int32_t *pTemperatureC)
01301 {
01302     bool success = false;
01303     char reg;
01304 
01305     if (gReady && (gpI2c != NULL)) {
01306         gpI2c->lock();
01307         // BCOLD is bit 1 of the charge current control register
01308         if (getRegister(0x02, &reg)) {
01309             success = true;
01310             if (pTemperatureC != NULL) {
01311                 *pTemperatureC = -10;
01312                 if ((reg & (1 << 1)) != 0) {
01313                     *pTemperatureC = -20;
01314                 }
01315             }
01316         }
01317         
01318 #ifdef DEBUG_BQ24295
01319         if (reg & (1 << 1)) {
01320             printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit is -20 C.\r\n", gAddress >> 1);
01321         } else {
01322             printf("BatteryChargerBq24295 (I2C 0x%02x): boost mode lower temperature limit is -10 C.\r\n", gAddress >> 1);
01323         }
01324 #endif
01325         gpI2c->unlock();
01326     }
01327 
01328     return success;
01329 }
01330     
01331 // Set the input voltage limit.
01332 bool BatteryChargerBq24295::setInputVoltageLimit (int32_t voltageMV)
01333 {
01334     bool success = false;
01335     char reg;
01336     int32_t codedValue;
01337 
01338     if (gReady && (gpI2c != NULL)) {
01339         gpI2c->lock();
01340         // Read the input source control register
01341         if (getRegister(0x00, &reg)) {
01342             // Input voltage limit is in bits 3 to 6
01343             // but it is coded to base "80 mV" with
01344             // an offset of 3880 mV.
01345             if ((voltageMV >= 3880) && (voltageMV <= 5080)) {
01346                 codedValue = voltageMV;
01347                 codedValue = (codedValue - 3880) / 80;
01348                 
01349                 reg &= ~(0x0f << 3);
01350                 reg |= (char) ((codedValue & 0x0f) << 3);
01351                 
01352                // Write to the input source control register
01353                 success = setRegister (0x00, reg);
01354 #ifdef DEBUG_BQ24295
01355                 if (success) {
01356                     printf("BatteryChargerBq24295 (I2C 0x%02x): input voltage limit now set to %.3f V.\r\n", gAddress >> 1, (float) voltageMV / 1000);
01357                 }
01358 #endif
01359             }
01360         }
01361         gpI2c->unlock();
01362     }
01363 
01364     return success;
01365 }
01366 
01367 // Get the input voltage limit.
01368 bool BatteryChargerBq24295::getInputVoltageLimit (int32_t *pVoltageMV)
01369 {
01370     bool success = false;
01371     char reg;
01372 
01373     if (gReady && (gpI2c != NULL)) {
01374         gpI2c->lock();
01375         // Read the input source control register
01376         if (getRegister(0x00, &reg)) {
01377             success = true;
01378             if (pVoltageMV != NULL) {
01379                 // Input voltage limit is in bits 3 to 6
01380                 // Base voltage
01381                 *pVoltageMV = 3880;
01382                 // Shift reg down and add the number of multiples
01383                 // of 80 mV
01384                 reg = (reg >> 3) & 0x0f;
01385                 *pVoltageMV += ((int32_t) reg) * 80;
01386 #ifdef DEBUG_BQ24295
01387                 printf("BatteryChargerBq24295 (I2C 0x%02x): input voltage limit is %.3f V.\r\n", gAddress >> 1, (float) *pVoltageMV / 1000);
01388 #endif
01389             }
01390         }
01391         gpI2c->unlock();
01392     }
01393 
01394     return success;
01395 }
01396 
01397 // Set the input current limit.
01398 bool BatteryChargerBq24295::setInputCurrentLimit (int32_t currentMA)
01399 {
01400     bool success = false;
01401     char reg;
01402     char codedValue;
01403 
01404     if (gReady && (gpI2c != NULL)) {
01405         gpI2c->lock();
01406         // Read the input source control register
01407         if (getRegister(0x00, &reg)) {
01408             // Input current limit is in bits 0 to 2, coded
01409             // such that the smallest limit is applied for
01410             // a range (e.g. 120 mA ends up as 100 mA rather
01411             // than 150 mA)
01412             if ((currentMA >= 100) && (currentMA <= 3000)) {
01413                 if (currentMA < 150) {
01414                     codedValue = 0;
01415                 } else if (currentMA < 500) {
01416                     codedValue = 1;
01417                 } else if (currentMA < 900) {
01418                     codedValue = 2;
01419                 } else if (currentMA < 1000) {
01420                     codedValue = 3;
01421                 } else if (currentMA < 1500) {
01422                     codedValue = 4;
01423                 } else if (currentMA < 2000) {
01424                     codedValue = 5;
01425                 } else if (currentMA < 3000) {
01426                     codedValue = 6;
01427                 } else {
01428                     codedValue = 7;
01429                 }                
01430                 reg &= ~(0x07 << 0);
01431                 reg |= codedValue;
01432                 
01433                // Write to the input source control register
01434                 success = setRegister (0x00, reg);
01435 #ifdef DEBUG_BQ24295
01436                 if (success) {
01437                     printf("BatteryChargerBq24295 (I2C 0x%02x): input current limit now set to %.3f A.\r\n", gAddress >> 1, (float) currentMA / 1000);
01438                 }
01439 #endif
01440             }
01441         }
01442         gpI2c->unlock();
01443     }
01444 
01445     return success;
01446 }
01447 
01448 // Get the input current limit.
01449 bool BatteryChargerBq24295::getInputCurrentLimit (int32_t *pCurrentMA)
01450 {
01451     bool success = false;
01452     char reg;
01453 
01454     if (gReady && (gpI2c != NULL)) {
01455         gpI2c->lock();
01456         // Read the input source control register
01457         if (getRegister(0x00, &reg)) {
01458             success = true;
01459             if (pCurrentMA != NULL) {
01460                 *pCurrentMA = 0;
01461                 // Input current limit is in bits 0 to 2
01462                 switch (reg & 0x07) {
01463                     case 0:
01464                         *pCurrentMA = 100;
01465                     break;
01466                     case 1:
01467                         *pCurrentMA = 150;
01468                     break;
01469                     case 2:
01470                         *pCurrentMA = 500;
01471                     break;
01472                     case 3:
01473                         *pCurrentMA = 900;
01474                     break;
01475                     case 4:
01476                         *pCurrentMA = 1000;
01477                     break;
01478                     case 5:
01479                         *pCurrentMA = 1500;
01480                     break;
01481                     case 6:
01482                         *pCurrentMA = 2000;
01483                     break;
01484                     case 7:
01485                         *pCurrentMA = 3000;
01486                     break;
01487                     default:
01488                         MBED_ASSERT(false);
01489                     break;
01490                 }
01491 #ifdef DEBUG_BQ24295
01492                 printf("BatteryChargerBq24295 (I2C 0x%02x): input current limit is %.3f A.\r\n", gAddress >> 1, (float) *pCurrentMA / 1000);
01493 #endif
01494             }
01495         }
01496         gpI2c->unlock();
01497     }
01498 
01499     return success;
01500 }
01501 
01502 // Enable input voltage or current limits.
01503 bool BatteryChargerBq24295::enableInputLimits (void)
01504 {
01505     bool success = false;
01506 
01507     if (gReady && (gpI2c != NULL)) {
01508         gpI2c->lock();
01509         // Input limit enable is bit 7 of the source control register
01510         success = setRegisterBits(0x00, (1 << 7));
01511 #ifdef DEBUG_BQ24295
01512         if (success) {
01513             printf("BatteryChargerBq24295 (I2C 0x%02x): input limits now ENABLED.\r\n", gAddress >> 1);
01514         }
01515 #endif
01516         gpI2c->unlock();
01517     }
01518 
01519     return success;
01520 }
01521 
01522 // Remove any input voltage or current limits.
01523 bool BatteryChargerBq24295::disableInputLimits (void)
01524 {
01525     bool success = false;
01526 
01527     if (gReady && (gpI2c != NULL)) {
01528         gpI2c->lock();
01529         // Input limit enable is bit 7 of the source control register
01530         success = clearRegisterBits(0x00, (1 << 7));
01531 #ifdef DEBUG_BQ24295
01532         if (success) {
01533             printf("BatteryChargerBq24295 (I2C 0x%02x): input limits now DISABLED.\r\n", gAddress >> 1);
01534         }
01535 #endif
01536         gpI2c->unlock();
01537     }
01538 
01539     return success;
01540 }
01541 
01542 // Check if input limits are enabled.
01543 bool BatteryChargerBq24295::areInputLimitsEnabled (void)
01544 {
01545     bool areEnabled = false;
01546     char reg;
01547     
01548     if (gReady && (gpI2c != NULL)) {
01549         gpI2c->lock();
01550         // Read the input source control register
01551         if (getRegister(0x00, &reg)) {
01552             // Input limit enable is bit 7 of the source control register
01553             if ((reg & (1 << 7)) != 0) {
01554                 areEnabled = true;
01555             }
01556 #ifdef DEBUG_BQ24295
01557             if (areEnabled) {
01558                 printf("BatteryChargerBq24295 (I2C 0x%02x): input limits are ENABLED.\r\n", gAddress >> 1);
01559             } else {
01560                 printf("BatteryChargerBq24295 (I2C 0x%02x): input limits are DISABLED.\r\n", gAddress >> 1);
01561             }
01562 #endif
01563         }
01564         gpI2c->unlock();
01565     }
01566 
01567     return areEnabled;
01568 }
01569 
01570 // Set the thermal regulation threshold for the chip.
01571 bool BatteryChargerBq24295::setChipThermalRegulationThreshold (int32_t temperatureC)
01572 {
01573     bool success = false;
01574     char reg;
01575     char codedValue;
01576 
01577     if (gReady && (gpI2c != NULL)) {
01578         gpI2c->lock();
01579         // Read the boost voltage/thermal regulation control register
01580         if (getRegister(0x06, &reg)) {
01581             // TREG is in bits 0 & 1
01582             if (temperatureC < 80) {
01583                 codedValue = 0;
01584             } else if (temperatureC < 100) {
01585                 codedValue = 1;
01586             } else if (temperatureC < 120) {
01587                 codedValue = 2;
01588             } else {
01589                 codedValue = 3;
01590             }
01591             reg &= ~0x03;
01592             reg |= (char) codedValue;
01593             // Write to boost voltage/thermal regulation control register
01594             success = setRegister (0x06, reg);
01595 #ifdef DEBUG_BQ24295
01596             if (success) {
01597                 printf("BatteryChargerBq24295 (I2C 0x%02x): chip thermal regulation threshold now set to %d C.\r\n", gAddress >> 1, (int) temperatureC);
01598             }
01599 #endif
01600         }
01601         gpI2c->unlock();
01602     }
01603 
01604     return success;
01605 }
01606 
01607 // Get the thermal regulation threshold for the chip.
01608 bool BatteryChargerBq24295::getChipThermalRegulationThreshold (int32_t *pTemperatureC)
01609 {
01610     bool success = false;
01611     char reg;
01612 
01613     if (gReady && (gpI2c != NULL)) {
01614         gpI2c->lock();
01615         /// TREG is in bits 0 & 1 of the boost voltage/thermal regulation control register
01616         if (getRegister(0x06, &reg)) {
01617             success = true;
01618             if (pTemperatureC != NULL) {
01619                 switch (reg & 0x03) {
01620                     case 0:
01621                         *pTemperatureC = 60;
01622                     break;
01623                     case 1:
01624                         *pTemperatureC = 80;
01625                     break;
01626                     case 2:
01627                         *pTemperatureC = 100;
01628                     break;
01629                     case 3:
01630                         *pTemperatureC = 120;
01631                     break;
01632                     default:
01633                         MBED_ASSERT(false);
01634                     break;
01635                 }
01636 #ifdef DEBUG_BQ24295
01637                 printf("BatteryChargerBq24295 (I2C 0x%02x): chip thermal regulation threshold is %d C.\r\n", gAddress >> 1, (int) *pTemperatureC);
01638 #endif
01639             }
01640         }
01641         gpI2c->unlock();
01642     }
01643 
01644     return success;
01645 }
01646     
01647 // Get the charger fault status as a bitmap.
01648 char BatteryChargerBq24295::getChargerFaults(void)
01649 {
01650     char bitmap = (char) CHARGER_FAULT_NONE;
01651     char reg;
01652 
01653     if (gReady && (gpI2c != NULL)) {
01654         gpI2c->lock();
01655         // Read the fault register
01656         if (getRegister(0x09, &reg)) {
01657             bitmap = reg;
01658 #ifdef DEBUG_BQ24295
01659             printf("BatteryChargerBq24295 (I2C 0x%02x): charge fault register 0x%02x.\r\n", gAddress >> 1, bitmap);
01660 #endif
01661         }
01662         gpI2c->unlock();
01663     }
01664 
01665     return bitmap;
01666 }
01667 
01668 // Feed the watchdog timer of the BQ24295 chip.
01669 bool BatteryChargerBq24295::feedWatchdog (void)
01670 {
01671     bool success = false;
01672 
01673     if (gReady && (gpI2c != NULL)) {
01674         gpI2c->lock();
01675         // Watchdog reset is done by setting bit 6 of the power on control register
01676         // to 1
01677         success = setRegisterBits(0x01, (1 << 6));
01678 #ifdef DEBUG_BQ24295
01679         if (success) {
01680             printf("BatteryChargerBq24295 (I2C 0x%02x): watchdog fed.\r\n", gAddress >> 1);
01681         }
01682 #endif
01683         gpI2c->unlock();
01684     }
01685 
01686     return success;
01687 }
01688 
01689 // Get the watchdog timer of the BQ24295 chip.
01690 bool BatteryChargerBq24295::getWatchdog (int32_t *pWatchdogS)
01691 {
01692     bool success = false;
01693     char reg;
01694 
01695     if (gReady && (gpI2c != NULL)) {
01696         gpI2c->lock();
01697         // Watchdog timer is in bits 4 and 5 of the charger termination/timer control
01698         // register, where 0 is disabled 01 is 40 secs, 10 is 80 secs and 11 is 160 secs
01699         success = getRegister(0x05, &reg);
01700         if (pWatchdogS != NULL) {
01701             switch ((reg >> 4) & 0x03) {
01702                 case 0x00:
01703                     *pWatchdogS = 0;
01704                 break;
01705                 case 0x01:
01706                     *pWatchdogS = 40;
01707                 break;
01708                 case 0x02:
01709                     *pWatchdogS = 80;
01710                 break;
01711                 case 0x03:
01712                     *pWatchdogS = 160;
01713                 break;
01714                 default:
01715                     MBED_ASSERT(false);
01716                 break;
01717             }
01718 #ifdef DEBUG_BQ24295
01719             if (success) {
01720                 printf("BatteryChargerBq24295 (I2C 0x%02x): watchdog is %d seconds.\r\n", gAddress >> 1, (int) *pWatchdogS);
01721             }
01722 #endif
01723         }
01724         gpI2c->unlock();
01725     }
01726 
01727     return success;
01728 }
01729 
01730 // Set the watchdog timer of the BQ24295 chip.
01731 bool BatteryChargerBq24295::setWatchdog (int32_t watchdogS)
01732 {
01733     bool success = false;
01734     char reg;
01735     char regValue = 0;
01736 
01737     if (gReady && (gpI2c != NULL)) {
01738         gpI2c->lock();
01739         // Watchdog timer is in bits 4 and 5 of the charger termination/timer control
01740         // register, where 0 is disabled 01 is 40 secs, 10 is 80 secs and 11 is 160 secs
01741         if (watchdogS > 80) {
01742             regValue = 0x03;
01743         } else if (watchdogS > 40) {
01744             regValue = 0x02;
01745         } else if (watchdogS > 0) {
01746             regValue = 0x01;
01747         }
01748         if (getRegister(0x05, &reg)) {
01749             // Clear the bits then set them
01750             reg &= ~(0x03 << 4);
01751             reg |= regValue << 4;
01752             success = setRegister(0x05, reg);
01753 #ifdef DEBUG_BQ24295
01754             if (success) {
01755                 printf("BatteryChargerBq24295 (I2C 0x%02x): watchdog set to %d seconds.\r\n", gAddress >> 1, (int) watchdogS);
01756             }
01757 #endif
01758         }
01759         gpI2c->unlock();
01760     }
01761 
01762     return success;
01763 }
01764 
01765 // Enable shipping mode.
01766 bool BatteryChargerBq24295::enableShippingMode (void)
01767 {
01768     bool success = false;
01769 
01770     if (gReady && (gpI2c != NULL)) {
01771         gpI2c->lock();
01772         // Have to disable the watchdog (bits 4 & 5 of charge termination/timer control register)
01773         if (clearRegisterBits(0x05, (1 << 4) || (1 << 5))) {
01774             // Now disable the BATFET, bit 5 of the misc operation control register
01775             success = setRegisterBits(0x07, (1 << 5));
01776 #ifdef DEBUG_BQ24295
01777             if (success) {
01778                 printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is now ENABLED.\r\n", gAddress >> 1);
01779             }
01780 #endif
01781         }
01782         gpI2c->unlock();
01783     }
01784 
01785     return success;
01786 }
01787 
01788 // Disable shipping mode.
01789 bool BatteryChargerBq24295::disableShippingMode (void)
01790 {
01791     bool success = false;
01792 
01793     if (gReady && (gpI2c != NULL)) {
01794         gpI2c->lock();
01795         // Set the watchdog timer back to default (bit 4 of charge termination/timer control register)
01796         if (setRegisterBits(0x05, (1 << 4))) {
01797             // Now enable the BATFET, bit 5 of the misc operation control register
01798             success = clearRegisterBits(0x07, (1 << 5));
01799 #ifdef DEBUG_BQ24295
01800             if (success) {
01801                 printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is now DISABLED.\r\n", gAddress >> 1);
01802             }
01803 #endif
01804         }
01805         gpI2c->unlock();
01806     }
01807 
01808     return success;
01809 }
01810 
01811 // Check if shipping mode is enabled.
01812 bool BatteryChargerBq24295::isShippingModeEnabled (void)
01813 {
01814     bool isEnabled = false;
01815     char reg;
01816     
01817     if (gReady && (gpI2c != NULL)) {
01818         gpI2c->lock();
01819         // To be in shipping mode the watchdog has to be disabled
01820         if (getRegister(0x05, &reg)) {
01821             // Check bits 4 & 5 of the charge termination/timer control register for zero
01822             if ((reg & ((1 << 4) || (1 << 5))) == 0) {
01823                 // Now see if the BATFET is disabled (bit 5 of the misc operation control register)
01824                 if (getRegister(0x07, &reg) && ((reg & (1 << 5)) != 0)) {
01825                     isEnabled = true;
01826                 }
01827             }
01828 #ifdef DEBUG_BQ24295
01829             if (isEnabled) {
01830                 printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is ENABLED.\r\n", gAddress >> 1);
01831             } else {
01832                 printf("BatteryChargerBq24295 (I2C 0x%02x): shipping mode is DISABLED.\r\n", gAddress >> 1);
01833             }
01834 #endif
01835         }
01836         gpI2c->unlock();
01837     }
01838 
01839     return isEnabled;
01840 }
01841 
01842 // Read a register on the chip.
01843 bool BatteryChargerBq24295::advancedGet(char address, char *pValue)
01844 {
01845     bool success = false;
01846     char value;
01847 
01848     if (gReady && (gpI2c != NULL)) {
01849         gpI2c->lock();
01850         // Read the register
01851         if (getRegister(address, &value)) {
01852             success = true;
01853 #ifdef DEBUG_BQ24295
01854             printf("BatteryChargerBq24295 (I2C 0x%02x): read 0x%02x from address 0x%02x.\n", gAddress >> 1, value, address);
01855 #endif
01856             if (pValue != NULL) {
01857                 *pValue = value;
01858             }
01859         }
01860         gpI2c->unlock();
01861     }
01862 
01863     return success;
01864 }
01865 
01866 // Set a register on the chip.
01867 // TODO test
01868 bool BatteryChargerBq24295::advancedSet(char address, char value)
01869 {
01870     bool success = false;
01871 
01872     if (gReady && (gpI2c != NULL)) {
01873         gpI2c->lock();
01874         // Set the register
01875         success = setRegister (address, value);
01876 #ifdef DEBUG_BQ24295
01877         if (success) {
01878             printf("BatteryChargerBq24295 (I2C 0x%02x): wrote 0x%02x  to address 0x%02x.\n", gAddress >> 1, value, address);
01879         }
01880 #endif
01881         gpI2c->unlock();
01882     }
01883 
01884     return success;
01885 }
01886 
01887 /* End Of File */