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:
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@0:c12a004a9113, 2014-11-27 (annotated)
- Committer:
- xeta05
- Date:
- Thu Nov 27 16:45:51 2014 +0000
- Revision:
- 0:c12a004a9113
- Child:
- 1:17f606b5b59b
initial revision
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
xeta05 | 0:c12a004a9113 | 1 | #include "mbed.h" |
xeta05 | 0:c12a004a9113 | 2 | #include "Rtc_bq32k.h" |
xeta05 | 0:c12a004a9113 | 3 | |
xeta05 | 0:c12a004a9113 | 4 | |
xeta05 | 0:c12a004a9113 | 5 | |
xeta05 | 0:c12a004a9113 | 6 | |
xeta05 | 0:c12a004a9113 | 7 | const char *Rtc_bq32k::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }; |
xeta05 | 0:c12a004a9113 | 8 | |
xeta05 | 0:c12a004a9113 | 9 | |
xeta05 | 0:c12a004a9113 | 10 | Rtc_bq32k::Rtc_bq32k(PinName sda, PinName scl) |
xeta05 | 0:c12a004a9113 | 11 | { |
xeta05 | 0:c12a004a9113 | 12 | // Create a new I2C object |
xeta05 | 0:c12a004a9113 | 13 | m_rtc = new I2C(sda, scl); |
xeta05 | 0:c12a004a9113 | 14 | |
xeta05 | 0:c12a004a9113 | 15 | // Set the frequency to standard 100kHz |
xeta05 | 0:c12a004a9113 | 16 | m_rtc->frequency(100000); |
xeta05 | 0:c12a004a9113 | 17 | |
xeta05 | 0:c12a004a9113 | 18 | } |
xeta05 | 0:c12a004a9113 | 19 | |
xeta05 | 0:c12a004a9113 | 20 | Rtc_bq32k::~Rtc_bq32k() |
xeta05 | 0:c12a004a9113 | 21 | { |
xeta05 | 0:c12a004a9113 | 22 | if (m_rtc != NULL) |
xeta05 | 0:c12a004a9113 | 23 | delete m_rtc; |
xeta05 | 0:c12a004a9113 | 24 | } |
xeta05 | 0:c12a004a9113 | 25 | |
xeta05 | 0:c12a004a9113 | 26 | bool Rtc_bq32k::setTime(Time_rtc& time, bool start ) |
xeta05 | 0:c12a004a9113 | 27 | { |
xeta05 | 0:c12a004a9113 | 28 | char buffer[7]; |
xeta05 | 0:c12a004a9113 | 29 | |
xeta05 | 0:c12a004a9113 | 30 | if (!read(0,buffer,7)) {return false;} |
xeta05 | 0:c12a004a9113 | 31 | |
xeta05 | 0:c12a004a9113 | 32 | // Now update only the time part (saving the existing flags) |
xeta05 | 0:c12a004a9113 | 33 | if (start) { buffer[0] &= 0x7F; } |
xeta05 | 0:c12a004a9113 | 34 | else { buffer[0] |= 0x80; } |
xeta05 | 0:c12a004a9113 | 35 | |
xeta05 | 0:c12a004a9113 | 36 | buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)&0x7f); |
xeta05 | 0:c12a004a9113 | 37 | buffer[1] = (decimalToBcd(time.min) &0x7f); //This way i am surethat OF bit i cleared |
xeta05 | 0:c12a004a9113 | 38 | buffer[2] = (buffer[2]& 0xC0) | (decimalToBcd(time.hour) & 0x3F);// 24 hours format |
xeta05 | 0:c12a004a9113 | 39 | buffer[3] = time.wday; |
xeta05 | 0:c12a004a9113 | 40 | buffer[4] = decimalToBcd(time.date); |
xeta05 | 0:c12a004a9113 | 41 | buffer[5] = decimalToBcd(time.mon); |
xeta05 | 0:c12a004a9113 | 42 | buffer[6] = decimalToBcd(time.year-2000); |
xeta05 | 0:c12a004a9113 | 43 | if (!write(0, buffer, 7) ) {return false;} |
xeta05 | 0:c12a004a9113 | 44 | return true; |
xeta05 | 0:c12a004a9113 | 45 | } |
xeta05 | 0:c12a004a9113 | 46 | |
xeta05 | 0:c12a004a9113 | 47 | bool Rtc_bq32k::getTime(Time_rtc& time) |
xeta05 | 0:c12a004a9113 | 48 | { |
xeta05 | 0:c12a004a9113 | 49 | char buffer[7]; |
xeta05 | 0:c12a004a9113 | 50 | if (!read(0, buffer, 7) ) {return false;} |
xeta05 | 0:c12a004a9113 | 51 | |
xeta05 | 0:c12a004a9113 | 52 | time.sec = bcdToDecimal(buffer[0]&0x7F); |
xeta05 | 0:c12a004a9113 | 53 | time.min = bcdToDecimal(buffer[1]&0x7F); |
xeta05 | 0:c12a004a9113 | 54 | time.hour = bcdToDecimal(buffer[2]&0x3F); |
xeta05 | 0:c12a004a9113 | 55 | time.wday = buffer[3]; |
xeta05 | 0:c12a004a9113 | 56 | time.date = bcdToDecimal(buffer[4]&0x3F); |
xeta05 | 0:c12a004a9113 | 57 | time.mon = bcdToDecimal(buffer[5]&0x1F); |
xeta05 | 0:c12a004a9113 | 58 | 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 |
xeta05 | 0:c12a004a9113 | 59 | |
xeta05 | 0:c12a004a9113 | 60 | return true; |
xeta05 | 0:c12a004a9113 | 61 | } |
xeta05 | 0:c12a004a9113 | 62 | |
xeta05 | 0:c12a004a9113 | 63 | bool Rtc_bq32k::startClock() |
xeta05 | 0:c12a004a9113 | 64 | { |
xeta05 | 0:c12a004a9113 | 65 | char strtStop; |
xeta05 | 0:c12a004a9113 | 66 | |
xeta05 | 0:c12a004a9113 | 67 | if (!read(0, &strtStop, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 68 | strtStop &= 0x7F;//pon el bit stop a 0 oscilando |
xeta05 | 0:c12a004a9113 | 69 | if (!write(0, &strtStop, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 70 | return true; |
xeta05 | 0:c12a004a9113 | 71 | } |
xeta05 | 0:c12a004a9113 | 72 | |
xeta05 | 0:c12a004a9113 | 73 | bool Rtc_bq32k::oscStatus() |
xeta05 | 0:c12a004a9113 | 74 | { |
xeta05 | 0:c12a004a9113 | 75 | char status; |
xeta05 | 0:c12a004a9113 | 76 | if (!read(1, &status, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 77 | if (status &= 0x80){return false;} |
xeta05 | 0:c12a004a9113 | 78 | else{return true;} |
xeta05 | 0:c12a004a9113 | 79 | } |
xeta05 | 0:c12a004a9113 | 80 | |
xeta05 | 0:c12a004a9113 | 81 | bool Rtc_bq32k::stopClock() |
xeta05 | 0:c12a004a9113 | 82 | { |
xeta05 | 0:c12a004a9113 | 83 | char strtStop; |
xeta05 | 0:c12a004a9113 | 84 | if (!read(0, &strtStop, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 85 | strtStop |= 0x80; |
xeta05 | 0:c12a004a9113 | 86 | if (!write(0, &strtStop, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 87 | return true; |
xeta05 | 0:c12a004a9113 | 88 | } |
xeta05 | 0:c12a004a9113 | 89 | |
xeta05 | 0:c12a004a9113 | 90 | bool Rtc_bq32k::setSquareWaveOutput(bool ena, SqwRateSelect_t rs) |
xeta05 | 0:c12a004a9113 | 91 | { |
xeta05 | 0:c12a004a9113 | 92 | char buffer[3],Cal_cfg1; |
xeta05 | 0:c12a004a9113 | 93 | if (!read(BQ32000_CAL_CFG1, &Cal_cfg1, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 94 | if (ena) |
xeta05 | 0:c12a004a9113 | 95 | { |
xeta05 | 0:c12a004a9113 | 96 | // Setting the frequency is a bit complicated on the BQ32000: |
xeta05 | 0:c12a004a9113 | 97 | buffer[0]=BQ32000_SFKEY1_VAL; |
xeta05 | 0:c12a004a9113 | 98 | buffer[1]=BQ32000_SFKEY2_VAL; |
xeta05 | 0:c12a004a9113 | 99 | buffer[2]=rs; |
xeta05 | 0:c12a004a9113 | 100 | if (!write(BQ32000_SFKEY1, buffer, 3)){return false; } |
xeta05 | 0:c12a004a9113 | 101 | Cal_cfg1=Cal_cfg1|0x40; //preserve the OUT,S and Calibration bits while setting the FT bit. |
xeta05 | 0:c12a004a9113 | 102 | } |
xeta05 | 0:c12a004a9113 | 103 | else{ Cal_cfg1=Cal_cfg1&0xBF;} //preserve the OUT,S and Calibration bits while clearing the FT bit. |
xeta05 | 0:c12a004a9113 | 104 | if (!write(BQ32000_CAL_CFG1, &Cal_cfg1, 1)) {return false;} |
xeta05 | 0:c12a004a9113 | 105 | return true; |
xeta05 | 0:c12a004a9113 | 106 | } |
xeta05 | 0:c12a004a9113 | 107 | bool Rtc_bq32k::setIRQLevel(bool level) |
xeta05 | 0:c12a004a9113 | 108 | { |
xeta05 | 0:c12a004a9113 | 109 | char Cal_cfg1; |
xeta05 | 0:c12a004a9113 | 110 | if (!read(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false;} |
xeta05 | 0:c12a004a9113 | 111 | if (level) |
xeta05 | 0:c12a004a9113 | 112 | { |
xeta05 | 0:c12a004a9113 | 113 | Cal_cfg1|=0x80;//set the Out bit |
xeta05 | 0:c12a004a9113 | 114 | } |
xeta05 | 0:c12a004a9113 | 115 | else |
xeta05 | 0:c12a004a9113 | 116 | { |
xeta05 | 0:c12a004a9113 | 117 | Cal_cfg1&=0x7F;//clear the Out bit |
xeta05 | 0:c12a004a9113 | 118 | } |
xeta05 | 0:c12a004a9113 | 119 | if (!write(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false;} |
xeta05 | 0:c12a004a9113 | 120 | return true; |
xeta05 | 0:c12a004a9113 | 121 | } |
xeta05 | 0:c12a004a9113 | 122 | bool Rtc_bq32k::setCalibration(int8_t value) |
xeta05 | 0:c12a004a9113 | 123 | { |
xeta05 | 0:c12a004a9113 | 124 | |
xeta05 | 0:c12a004a9113 | 125 | char Cal_cfg1; |
xeta05 | 0:c12a004a9113 | 126 | if (value > 31) value = 31;//be sure to be inside the limits |
xeta05 | 0:c12a004a9113 | 127 | if (value < -31) value = -31; |
xeta05 | 0:c12a004a9113 | 128 | value = ((char) (value < 0) ? -value | (1<<BQ32000__CAL_S) : value);//generate the calibration plus sign bit |
xeta05 | 0:c12a004a9113 | 129 | |
xeta05 | 0:c12a004a9113 | 130 | if (!read(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false;} |
xeta05 | 0:c12a004a9113 | 131 | //and write only the calibration plus sign bits |
xeta05 | 0:c12a004a9113 | 132 | Cal_cfg1 |= (Cal_cfg1 & 0xC0)|value; |
xeta05 | 0:c12a004a9113 | 133 | if (!write(BQ32000_CAL_CFG1, &Cal_cfg1, 1)){return false; } |
xeta05 | 0:c12a004a9113 | 134 | return true; |
xeta05 | 0:c12a004a9113 | 135 | } |
xeta05 | 0:c12a004a9113 | 136 | void Rtc_bq32k::setCharger(int state) |
xeta05 | 0:c12a004a9113 | 137 | { |
xeta05 | 0:c12a004a9113 | 138 | char value; |
xeta05 | 0:c12a004a9113 | 139 | // First disable charger regardless of state (prevents it from |
xeta05 | 0:c12a004a9113 | 140 | // possible starting up in the high voltage mode when the low |
xeta05 | 0:c12a004a9113 | 141 | // voltage mode is requested): |
xeta05 | 0:c12a004a9113 | 142 | value=0; |
xeta05 | 0:c12a004a9113 | 143 | write(BQ32000_TCH2, &value, 1); |
xeta05 | 0:c12a004a9113 | 144 | write(BQ32000_CFG2, &value, 1); |
xeta05 | 0:c12a004a9113 | 145 | if (state <= 0 || state > 2) return; |
xeta05 | 0:c12a004a9113 | 146 | |
xeta05 | 0:c12a004a9113 | 147 | value=BQ32000_CHARGE_ENABLE;//TCHE bits written |
xeta05 | 0:c12a004a9113 | 148 | |
xeta05 | 0:c12a004a9113 | 149 | if (state == 2) |
xeta05 | 0:c12a004a9113 | 150 | { |
xeta05 | 0:c12a004a9113 | 151 | // High voltage charge enable: |
xeta05 | 0:c12a004a9113 | 152 | value|=1<<BQ32000__TCFE_BIT; |
xeta05 | 0:c12a004a9113 | 153 | } |
xeta05 | 0:c12a004a9113 | 154 | |
xeta05 | 0:c12a004a9113 | 155 | write(BQ32000_CFG2, &value, 1); |
xeta05 | 0:c12a004a9113 | 156 | // Now enable charger: |
xeta05 | 0:c12a004a9113 | 157 | value=(1 << BQ32000__TCH2_BIT); |
xeta05 | 0:c12a004a9113 | 158 | write(BQ32000_TCH2, &value, 1); |
xeta05 | 0:c12a004a9113 | 159 | |
xeta05 | 0:c12a004a9113 | 160 | } |
xeta05 | 0:c12a004a9113 | 161 | |
xeta05 | 0:c12a004a9113 | 162 | bool Rtc_bq32k::read(int address, char *buffer, int len) |
xeta05 | 0:c12a004a9113 | 163 | { |
xeta05 | 0:c12a004a9113 | 164 | char buffer2[2] = {(char)address, 0}; |
xeta05 | 0:c12a004a9113 | 165 | |
xeta05 | 0:c12a004a9113 | 166 | // m_rtc->start(); |
xeta05 | 0:c12a004a9113 | 167 | if (m_rtc->write(0xd0, buffer2, 1) != 0) { |
xeta05 | 0:c12a004a9113 | 168 | m_rtc->stop(); |
xeta05 | 0:c12a004a9113 | 169 | return false; |
xeta05 | 0:c12a004a9113 | 170 | } |
xeta05 | 0:c12a004a9113 | 171 | if (m_rtc->read(0xd0, buffer, len) != 0) {return false;} |
xeta05 | 0:c12a004a9113 | 172 | m_rtc->stop(); |
xeta05 | 0:c12a004a9113 | 173 | return true; |
xeta05 | 0:c12a004a9113 | 174 | } |
xeta05 | 0:c12a004a9113 | 175 | |
xeta05 | 0:c12a004a9113 | 176 | bool Rtc_bq32k::write(int address, char *buffer, int len) |
xeta05 | 0:c12a004a9113 | 177 | { |
xeta05 | 0:c12a004a9113 | 178 | char buffer2[10]; |
xeta05 | 0:c12a004a9113 | 179 | buffer2[0] = address&0xFF; |
xeta05 | 0:c12a004a9113 | 180 | for (int i = 0 ; i < len ; i++) |
xeta05 | 0:c12a004a9113 | 181 | buffer2[i+1] = buffer[i]; |
xeta05 | 0:c12a004a9113 | 182 | |
xeta05 | 0:c12a004a9113 | 183 | // m_rtc->start(); |
xeta05 | 0:c12a004a9113 | 184 | if (m_rtc->write(0xd0, buffer2, len+1) != 0) |
xeta05 | 0:c12a004a9113 | 185 | { |
xeta05 | 0:c12a004a9113 | 186 | m_rtc->stop(); |
xeta05 | 0:c12a004a9113 | 187 | return false; |
xeta05 | 0:c12a004a9113 | 188 | } |
xeta05 | 0:c12a004a9113 | 189 | m_rtc->stop(); |
xeta05 | 0:c12a004a9113 | 190 | return true; |
xeta05 | 0:c12a004a9113 | 191 | } |
xeta05 | 0:c12a004a9113 | 192 |