This is a class for using the BQ32000 Real Time Clock chip from TI.

BQ32000

This is a class for using the BQ32000 Real Time Clock chip from TI.This is supossed to be pin and code compatible with the most usual DS1307. It is pin compatible as you can see:

/media/uploads/xeta05/bq32000.jpg

On the code side it is almost compatible, with some advanced functions added (trickle charge, calibration) and minor differences in the registers, For example is only capable of generating 1 Hz and 512 Hz square wave.

This library is based on the DS1307 library by Henry Leinen http://developer.mbed.org/users/leihen/code/RTC-DS1307/file/ee81f2c5a706

The trickle charge and calibration are included in the code but not tested against the chip.

Rtc_bq32k.cpp

Committer:
xeta05
Date:
2014-11-27
Revision:
1:17f606b5b59b
Parent:
0:c12a004a9113

File content as of revision 1:17f606b5b59b:

/* Rtc_bq32k.cpp */
/*2014/11/27 Oskar Lopez de Gamboa
*/
/* Copyright (c) <2014> <Oskar Lopez de Gamboa>, MIT License
 *
 * 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 THE AUTHORS OR COPYRIGHT HOLDERS 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.
 */
 
#include "mbed.h"
#include "Rtc_bq32k.h"

const char *Rtc_bq32k::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };    


Rtc_bq32k::Rtc_bq32k(PinName sda, PinName scl)
{
    //  Create a new I2C object
    m_rtc = new I2C(sda, scl);
        
    // Set the frequency to standard 100kHz
    m_rtc->frequency(100000);
    
}

Rtc_bq32k::~Rtc_bq32k()
{
    if (m_rtc != NULL)
        delete m_rtc;
}

bool Rtc_bq32k::setTime(Time_rtc& time, bool start )
{
    char buffer[7];
    
    if (!read(0,buffer,7)) {return false;}
    
    //  Now update only the time part (saving the existing flags)
    if (start) { buffer[0] &= 0x7F; } 
    else { buffer[0] |= 0x80; } 
        
    buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)&0x7f);
    buffer[1] = (decimalToBcd(time.min) &0x7f);         //This way i am surethat OF bit i cleared
    buffer[2] = (buffer[2]& 0xC0) | (decimalToBcd(time.hour) & 0x3F);// 24 hours format
    buffer[3] = time.wday;
    buffer[4] = decimalToBcd(time.date);
    buffer[5] = decimalToBcd(time.mon);
    buffer[6] = decimalToBcd(time.year-2000);
    if (!write(0, buffer, 7) ) {return false;}
    return true;
}

bool Rtc_bq32k::getTime(Time_rtc& time)
{
    char buffer[7];
    if (!read(0, buffer, 7) ) {return false;}
    
    time.sec = bcdToDecimal(buffer[0]&0x7F);
    time.min = bcdToDecimal(buffer[1]&0x7F);
    time.hour = bcdToDecimal(buffer[2]&0x3F);  
    time.wday = buffer[3]; 
    time.date = bcdToDecimal(buffer[4]&0x3F);
    time.mon = bcdToDecimal(buffer[5]&0x1F);
    time.year = bcdToDecimal(buffer[6]) + 2000;   //  plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900
    
    return true;
}

bool Rtc_bq32k::startClock()
{
    char strtStop;
    
    if (!read(0, &strtStop, 1)) {return false;}
    strtStop &= 0x7F;//pon el bit stop a 0 oscilando 
    if (!write(0, &strtStop, 1)) {return false;}
    return true;
}

bool Rtc_bq32k::oscStatus()
{
    char status;
    if (!read(1, &status, 1)) {return false;}
    if (status &= 0x80){return false;}
    else{return true;}
}

bool Rtc_bq32k::stopClock()
{
    char strtStop; 
    if (!read(0, &strtStop, 1)) {return false;} 
    strtStop |= 0x80;  
    if (!write(0, &strtStop, 1)) {return false;}
    return true;
}

bool Rtc_bq32k::setSquareWaveOutput(bool ena, SqwRateSelect_t rs)
{  
    char buffer[3],Cal_cfg1;
    if (!read(BQ32000_CAL_CFG1, &Cal_cfg1, 1)) {return false;}    
    if (ena) 
    {
        // Setting the frequency is a bit complicated on the BQ32000:
        buffer[0]=BQ32000_SFKEY1_VAL;
        buffer[1]=BQ32000_SFKEY2_VAL;
        buffer[2]=rs;
        if (!write(BQ32000_SFKEY1, buffer, 3)){return false; }
        Cal_cfg1=Cal_cfg1|0x40;     //preserve the OUT,S and Calibration bits while setting the FT bit.
    }
    else{ Cal_cfg1=Cal_cfg1&0xBF;}  //preserve the OUT,S and Calibration bits while clearing the FT bit.
    if (!write(BQ32000_CAL_CFG1, &Cal_cfg1, 1)) {return false;}
    return true;
}
bool Rtc_bq32k::setIRQLevel(bool level)
{
    char Cal_cfg1;
    if (!read(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false;}
    if (level)
    {
        Cal_cfg1|=0x80;//set the Out bit
    }
    else
    {
        Cal_cfg1&=0x7F;//clear the Out bit
    }
     if (!write(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false;}
    return true;
}
bool Rtc_bq32k::setCalibration(int8_t value) 
{
    
    char Cal_cfg1;
    if (value > 31) value = 31;//be sure to be inside the limits
    if (value < -31) value = -31;
    value = ((char) (value < 0) ? -value | (1<<BQ32000__CAL_S) : value);//generate the calibration plus sign bit
    
    if (!read(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false;}
    //and write only the calibration plus sign bits
    Cal_cfg1 |= (Cal_cfg1 & 0xC0)|value;
    if (!write(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false; }
     return true;
}
void Rtc_bq32k::setCharger(int state) 
{
    char value;
    // First disable charger regardless of state (prevents it from
    // possible starting up in the high voltage mode when the low
    // voltage mode is requested):
    value=0;
    write(BQ32000_TCH2, &value, 1);
    write(BQ32000_CFG2, &value, 1);
    if (state <= 0 || state > 2) return;
    
    value=BQ32000_CHARGE_ENABLE;//TCHE bits written
    
    if (state == 2)
    {
        // High voltage charge enable:
        value|=1<<BQ32000__TCFE_BIT;
    }
    
    write(BQ32000_CFG2, &value, 1);
    // Now enable charger:
    value=(1 << BQ32000__TCH2_BIT);
    write(BQ32000_TCH2, &value, 1);
    
}

bool Rtc_bq32k::read(int address, char *buffer, int len)
{
    char buffer2[2] = {(char)address, 0};
    
//    m_rtc->start();
    if (m_rtc->write(BQ32000_ADDRESS, buffer2, 1) != 0) {
        m_rtc->stop();
        return false;
    }
    if (m_rtc->read(BQ32000_ADDRESS, buffer, len) != 0) {return false;}
    m_rtc->stop();
    return true;
}

bool Rtc_bq32k::write(int address, char *buffer, int len)
{
    char buffer2[10];
    buffer2[0] = address&0xFF;
    for (int i = 0 ; i < len ; i++)
        buffer2[i+1] = buffer[i];

//    m_rtc->start();        
    if (m_rtc->write(BQ32000_ADDRESS, buffer2, len+1) != 0) 
    {
        m_rtc->stop();
        return false;
    }
    m_rtc->stop();
    return true;
}