Skip to content

Commit e49bb2f

Browse files
author
JChristensen
committed
Move I2C defines from .h file to .cpp file to avoid including unneeded libraries.
More efficient BCD/Decimal conversion functions. Document vbaten() method in ReadMe.
1 parent 44faa41 commit e49bb2f

File tree

3 files changed

+81
-65
lines changed

3 files changed

+81
-65
lines changed

MCP79412RTC.cpp

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,53 @@
1919
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
2020
* letter to Creative Commons, 171 Second Street, Suite 300, *
2121
* San Francisco, California, 94105, USA. *
22-
*----------------------------------------------------------------------*/
22+
*----------------------------------------------------------------------*/
2323

24-
#include <Wire.h>
25-
#include <TinyWireM.h>
2624
#include "MCP79412RTC.h"
2725

26+
//define release-independent I2C functions
27+
#if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
28+
#include <TinyWireM.h>
29+
#define i2cBegin TinyWireM.begin
30+
#define i2cBeginTransmission TinyWireM.beginTransmission
31+
#define i2cEndTransmission TinyWireM.endTransmission
32+
#define i2cRequestFrom TinyWireM.requestFrom
33+
#define i2cRead TinyWireM.receive
34+
#define i2cWrite TinyWireM.send
35+
#elif ARDUINO >= 100
36+
#include <Wire.h>
37+
#define i2cBegin Wire.begin
38+
#define i2cBeginTransmission Wire.beginTransmission
39+
#define i2cEndTransmission Wire.endTransmission
40+
#define i2cRequestFrom Wire.requestFrom
41+
#define i2cRead Wire.read
42+
#define i2cWrite Wire.write
43+
#else
44+
#include <Wire.h>
45+
#define i2cBegin Wire.begin
46+
#define i2cBeginTransmission Wire.beginTransmission
47+
#define i2cEndTransmission Wire.endTransmission
48+
#define i2cRequestFrom Wire.requestFrom
49+
#define i2cRead Wire.receive
50+
#define i2cWrite Wire.send
51+
#endif
52+
2853
/*----------------------------------------------------------------------*
2954
* Constructor. *
3055
*----------------------------------------------------------------------*/
3156
MCP79412RTC::MCP79412RTC()
3257
{
3358
i2cBegin();
3459
}
35-
60+
3661
/*----------------------------------------------------------------------*
3762
* Read the current time from the RTC and return it as a time_t value. *
3863
* Returns a zero value if RTC not present (I2C I/O error). *
3964
*----------------------------------------------------------------------*/
4065
time_t MCP79412RTC::get(void)
4166
{
4267
tmElements_t tm;
43-
68+
4469
if ( read(tm) )
4570
return( makeTime(tm) );
4671
else
@@ -55,7 +80,7 @@ void MCP79412RTC::set(time_t t)
5580
tmElements_t tm;
5681

5782
breakTime(t, tm);
58-
write(tm);
83+
write(tm);
5984
}
6085

6186
/*----------------------------------------------------------------------*
@@ -72,7 +97,7 @@ boolean MCP79412RTC::read(tmElements_t &tm)
7297
else {
7398
//request 7 bytes (secs, min, hr, dow, date, mth, yr)
7499
i2cRequestFrom(RTC_ADDR, tmNbrFields);
75-
tm.Second = bcd2dec(i2cRead() & ~_BV(ST));
100+
tm.Second = bcd2dec(i2cRead() & ~_BV(ST));
76101
tm.Minute = bcd2dec(i2cRead());
77102
tm.Hour = bcd2dec(i2cRead() & ~_BV(HR1224)); //assumes 24hr clock
78103
tm.Wday = i2cRead() & ~(_BV(OSCON) | _BV(VBAT) | _BV(VBATEN)); //mask off OSCON, VBAT, VBATEN bits
@@ -90,19 +115,19 @@ void MCP79412RTC::write(tmElements_t &tm)
90115
{
91116
i2cBeginTransmission(RTC_ADDR);
92117
i2cWrite((uint8_t)TIME_REG);
93-
i2cWrite((uint8_t)0x00); //stops the oscillator (Bit 7, ST == 0)
118+
i2cWrite((uint8_t)0x00); //stops the oscillator (Bit 7, ST == 0)
94119
i2cWrite(dec2bcd(tm.Minute));
95120
i2cWrite(dec2bcd(tm.Hour)); //sets 24 hour format (Bit 6 == 0)
96121
i2cWrite(tm.Wday | _BV(VBATEN)); //enable battery backup operation
97122
i2cWrite(dec2bcd(tm.Day));
98123
i2cWrite(dec2bcd(tm.Month));
99-
i2cWrite(dec2bcd(tmYearToY2k(tm.Year)));
100-
i2cEndTransmission();
124+
i2cWrite(dec2bcd(tmYearToY2k(tm.Year)));
125+
i2cEndTransmission();
101126

102127
i2cBeginTransmission(RTC_ADDR);
103128
i2cWrite((uint8_t)TIME_REG);
104129
i2cWrite(dec2bcd(tm.Second) | _BV(ST)); //set the seconds and start the oscillator (Bit 7, ST == 1)
105-
i2cEndTransmission();
130+
i2cEndTransmission();
106131
}
107132

108133
/*----------------------------------------------------------------------*
@@ -125,7 +150,7 @@ void MCP79412RTC::ramWrite(byte addr, byte *values, byte nBytes)
125150
i2cBeginTransmission(RTC_ADDR);
126151
i2cWrite(addr);
127152
for (byte i=0; i<nBytes; i++) i2cWrite(values[i]);
128-
i2cEndTransmission();
153+
i2cEndTransmission();
129154
}
130155

131156
/*----------------------------------------------------------------------*
@@ -135,7 +160,7 @@ void MCP79412RTC::ramWrite(byte addr, byte *values, byte nBytes)
135160
byte MCP79412RTC::ramRead(byte addr)
136161
{
137162
byte value;
138-
163+
139164
ramRead(addr, &value, 1);
140165
return value;
141166
}
@@ -150,7 +175,7 @@ void MCP79412RTC::ramRead(byte addr, byte *values, byte nBytes)
150175
{
151176
i2cBeginTransmission(RTC_ADDR);
152177
i2cWrite(addr);
153-
i2cEndTransmission();
178+
i2cEndTransmission();
154179
i2cRequestFrom( (uint8_t)RTC_ADDR, nBytes );
155180
for (byte i=0; i<nBytes; i++) values[i] = i2cRead();
156181
}
@@ -191,7 +216,7 @@ void MCP79412RTC::sramWrite(byte addr, byte *values, byte nBytes)
191216
byte MCP79412RTC::sramRead(byte addr)
192217
{
193218
byte value;
194-
219+
195220
ramRead( (addr & (SRAM_SIZE - 1) ) + SRAM_START_ADDR, &value, 1 );
196221
return value;
197222
}
@@ -257,7 +282,7 @@ byte MCP79412RTC::eepromRead(byte addr)
257282
{
258283
byte value;
259284

260-
eepromRead( addr & (EEPROM_SIZE - 1), &value, 1 );
285+
eepromRead( addr & (EEPROM_SIZE - 1), &value, 1 );
261286
return value;
262287
}
263288

@@ -279,7 +304,7 @@ void MCP79412RTC::eepromRead(byte addr, byte *values, byte nBytes)
279304
#endif
280305
i2cBeginTransmission(EEPROM_ADDR);
281306
i2cWrite( addr & (EEPROM_SIZE - 1) );
282-
i2cEndTransmission();
307+
i2cEndTransmission();
283308
i2cRequestFrom( (uint8_t)EEPROM_ADDR, nBytes );
284309
for (byte i=0; i<nBytes; i++) values[i] = i2cRead();
285310
}
@@ -292,16 +317,16 @@ byte MCP79412RTC::eepromWait(void)
292317
{
293318
byte waitCount = 0;
294319
byte txStatus;
295-
320+
296321
do
297322
{
298323
++waitCount;
299324
i2cBeginTransmission(EEPROM_ADDR);
300325
i2cWrite((uint8_t)0);
301326
txStatus = i2cEndTransmission();
302-
327+
303328
} while (txStatus != 0);
304-
329+
305330
return waitCount;
306331
}
307332

@@ -314,9 +339,9 @@ byte MCP79412RTC::eepromWait(void)
314339
int MCP79412RTC::calibRead(void)
315340
{
316341
byte val = ramRead(CALIB_REG);
317-
342+
318343
if ( val & 0x80 ) return -(val & 0x7F);
319-
else return val;
344+
else return val;
320345
}
321346

322347
/*----------------------------------------------------------------------*
@@ -327,7 +352,7 @@ int MCP79412RTC::calibRead(void)
327352
void MCP79412RTC::calibWrite(int value)
328353
{
329354
byte calibVal;
330-
355+
331356
if (value >= -127 && value <= 127) {
332357
calibVal = abs(value);
333358
if (value < 0) calibVal += 128;
@@ -344,7 +369,7 @@ void MCP79412RTC::idRead(byte *uniqueID)
344369
{
345370
i2cBeginTransmission(EEPROM_ADDR);
346371
i2cWrite(UNIQUE_ID_ADDR);
347-
i2cEndTransmission();
372+
i2cEndTransmission();
348373
i2cRequestFrom( EEPROM_ADDR, UNIQUE_ID_SIZE );
349374
for (byte i=0; i<UNIQUE_ID_SIZE; i++) uniqueID[i] = i2cRead();
350375
}
@@ -359,7 +384,7 @@ void MCP79412RTC::idRead(byte *uniqueID)
359384
void MCP79412RTC::getEUI64(byte *uniqueID)
360385
{
361386
byte rtcID[8];
362-
387+
363388
idRead(rtcID);
364389
if (rtcID[0] == 0xFF && rtcID[1] == 0xFF) {
365390
rtcID[0] = rtcID[2];
@@ -418,10 +443,10 @@ boolean MCP79412RTC::powerFail(time_t *powerDown, time_t *powerUp)
418443
up.Day = bcd2dec(i2cRead());
419444
up.Month = bcd2dec(i2cRead() & 0x1F); //mask off the day, we don't need it
420445
up.Year = yr; //assume current year
421-
446+
422447
*powerDown = makeTime(dn);
423448
*powerUp = makeTime(up);
424-
449+
425450
//clear the VBAT bit, which causes the RTC hardware to clear the timestamps too.
426451
//I suppose there is a risk here that the day has changed since we read it,
427452
//but the Day of Week is actually redundant data and the makeTime() function
@@ -481,7 +506,7 @@ void MCP79412RTC::setAlarm(uint8_t alarmNumber, time_t alarmTime)
481506
i2cWrite( (day & 0xF8) + tm.Wday );
482507
i2cWrite(dec2bcd(tm.Day));
483508
i2cWrite(dec2bcd(tm.Month));
484-
i2cEndTransmission();
509+
i2cEndTransmission();
485510
}
486511

487512
/*----------------------------------------------------------------------*
@@ -534,7 +559,7 @@ boolean MCP79412RTC::alarm(uint8_t alarmNumber)
534559
void MCP79412RTC::out(boolean level)
535560
{
536561
uint8_t ctrlReg;
537-
562+
538563
ramRead(CTRL_REG, &ctrlReg, 1);
539564
if (level)
540565
ctrlReg |= _BV(OUT);
@@ -558,7 +583,7 @@ void MCP79412RTC::out(boolean level)
558583
void MCP79412RTC::alarmPolarity(boolean polarity)
559584
{
560585
uint8_t alm0Day;
561-
586+
562587
ramRead(ALM0_DAY, &alm0Day, 1);
563588
if (polarity)
564589
alm0Day |= _BV(OUT);
@@ -590,31 +615,31 @@ boolean MCP79412RTC::isRunning(void)
590615
void MCP79412RTC::vbaten(boolean enable)
591616
{
592617
uint8_t day;
593-
618+
594619
ramRead(DAY_REG, &day, 1);
595620
if (enable)
596621
day |= _BV(VBATEN);
597622
else
598623
day &= ~_BV(VBATEN);
599-
624+
600625
ramWrite(DAY_REG, &day, 1);
601626
return;
602627
}
603628

604629
/*----------------------------------------------------------------------*
605630
* Decimal-to-BCD conversion *
606631
*----------------------------------------------------------------------*/
607-
uint8_t MCP79412RTC::dec2bcd(uint8_t num)
632+
uint8_t MCP79412RTC::dec2bcd(uint8_t n)
608633
{
609-
return ((num / 10 * 16) + (num % 10));
634+
return n + 6 * (n / 10);
610635
}
611636

612637
/*----------------------------------------------------------------------*
613638
* BCD-to-Decimal conversion *
614639
*----------------------------------------------------------------------*/
615-
uint8_t MCP79412RTC::bcd2dec(uint8_t num)
640+
uint8_t __attribute__ ((noinline)) MCP79412RTC::bcd2dec(uint8_t n)
616641
{
617-
return ((num / 16 * 10) + (num % 16));
642+
return n - 6 * (n >> 4);
618643
}
619644

620645
MCP79412RTC RTC = MCP79412RTC(); //instantiate an RTC object

MCP79412RTC.h

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,16 @@
1919
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
2020
* letter to Creative Commons, 171 Second Street, Suite 300, *
2121
* San Francisco, California, 94105, USA. *
22-
*----------------------------------------------------------------------*/
22+
*----------------------------------------------------------------------*/
2323

2424
#ifndef MCP79412RTC_h
2525
#define MCP79412RTC_h
2626
#include <Time.h>
2727

2828
#if defined(ARDUINO) && ARDUINO >= 100
29-
#include <Arduino.h>
29+
#include <Arduino.h>
3030
#else
31-
#include <WProgram.h>
32-
#endif
33-
34-
//define release-independent I2C functions
35-
#if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
36-
#define i2cBegin TinyWireM.begin
37-
#define i2cBeginTransmission TinyWireM.beginTransmission
38-
#define i2cEndTransmission TinyWireM.endTransmission
39-
#define i2cRequestFrom TinyWireM.requestFrom
40-
#define i2cRead TinyWireM.receive
41-
#define i2cWrite TinyWireM.send
42-
#elif ARDUINO >= 100
43-
#define i2cBegin Wire.begin
44-
#define i2cBeginTransmission Wire.beginTransmission
45-
#define i2cEndTransmission Wire.endTransmission
46-
#define i2cRequestFrom Wire.requestFrom
47-
#define i2cRead Wire.read
48-
#define i2cWrite Wire.write
49-
#else
50-
#define i2cBegin Wire.begin
51-
#define i2cBeginTransmission Wire.beginTransmission
52-
#define i2cEndTransmission Wire.endTransmission
53-
#define i2cRequestFrom Wire.requestFrom
54-
#define i2cRead Wire.receive
55-
#define i2cWrite Wire.send
31+
#include <WProgram.h>
5632
#endif
5733

5834
//MCP7941x I2C Addresses
@@ -62,7 +38,7 @@
6238
//MCP7941x Register Addresses
6339
#define TIME_REG 0x00 //7 registers, Seconds, Minutes, Hours, DOW, Date, Month, Year
6440
#define DAY_REG 0x03 //the RTC Day register contains the OSCON, VBAT, and VBATEN bits
65-
#define YEAR_REG 0x06 //RTC year register
41+
#define YEAR_REG 0x06 //RTC year register
6642
#define CTRL_REG 0x07 //control register
6743
#define CALIB_REG 0x08 //calibration register
6844
#define UNLOCK_ID_REG 0x09 //unlock ID register
@@ -93,7 +69,7 @@ enum {SQWAVE_1_HZ, SQWAVE_4096_HZ, SQWAVE_8192_HZ, SQWAVE_32768_HZ, SQWAVE_NONE}
9369
//Other Control Bits
9470
#define ST 7 //Seconds register (TIME_REG) oscillator start/stop bit, 1==Start, 0==Stop
9571
#define HR1224 6 //Hours register (TIME_REG+2) 12 or 24 hour mode (24 hour mode==0)
96-
#define AMPM 5 //Hours register (TIME_REG+2) AM/PM bit for 12 hour mode
72+
#define AMPM 5 //Hours register (TIME_REG+2) AM/PM bit for 12 hour mode
9773
#define OSCON 5 //Day register (TIME_REG+3) oscillator running (set and cleared by hardware)
9874
#define VBAT 4 //Day register (TIME_REG+3) set by hardware when Vcc fails and RTC runs on battery.
9975
//VBAT is cleared by software, clearing VBAT also clears the timestamp registers

ReadMe.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,21 @@ RTC.idRead(buf);
465465
```
466466
--------------------------------------------------------------------------------
467467

468+
###vbaten(boolean enable)
469+
#####Description
470+
Set or clear the VBATEN bit. Setting the bit powers the clock and SRAM from the backup battery when Vcc falls. Note that setting the time via set() or write() sets the VBATEN bit.
471+
#####Syntax
472+
`RTC.vbaten(boolean enable);`
473+
#####Parameters
474+
**enable:** true or false *(boolean)*
475+
#####Returns
476+
None.
477+
#####Example
478+
```c++
479+
RTC.vbaten(false);
480+
```
481+
--------------------------------------------------------------------------------
482+
468483
###getEUI64(byte *uniqueID)
469484
#####Description
470485
Returns an EUI-64 ID. For an MCP79412, calling this function is equivalent to calling `idRead()`. For an MCP79411, the EUI-48 ID is converted to EUI-64. Caller must provide an 8-byte array to contain the results.

0 commit comments

Comments
 (0)