As the dec2bcd() is used when writing to the RTC the gained time is only substantial when one writes alarm times often.
If one need to write the time to the RTC often it is time to replace the backup battery (or the RTC altogether)
Using the JeeLabs algorithms, a test sketch increased by about 150 bytes, due to the compiler inlining bcd2dec. Adding the noinline attribute as below resulted in only a 4 byte increase.
dec2bcd: 13576
dec2bcd2: 1896 ... the weird 103 calculation still wins handily, 86% reduction.
dec2bcd3: 6612 ... but this is no slouch, still a significant improvement, 51% reduction.
The following divide by 10 works for all 8-bit values but requires an 11 bit shift so it takes an extra cycle.
q = (205*n) >> 11;
Very true, however the BCD values will never be higher than 99(HEX) representing 99(DEC).
Given the fact that for a RTC the highest number need to be converted is 59 (OK we need to reimplement after 2059 - 45 years from now) seconds, minutes = ..59; hours = ..23; days= ..31; months ..12 ; weekdays = ..7; weeks=0..53; years=13..
So we can have an even simpler mul/shift, which has an even better time
uint8_t dec2bcd4(uint8_t n)
{
uint16_t a = n;
byte b = (a*26) >> 8; // b = (a*13) >> 7 was OK but slower!
return n + b*6;
}
The aspect of RTC libraries I have tried to optimize is conversion of RTC chip register values to Unix epoch time. This value is often used in data logging since the Unix definition is in Coordinated Universal Time (UTC/GMT).
I often use the year 2000 instead of 1970. Epoch time is the number of seconds since midnight 1 Jan of the epoch year in UTC.
My code takes about 31.5 microseconds per conversion. Here is a test sketch. It does not read the RTC.
// Time starts 2000-1-1 For Linux 1970-1-1 is used.
//const uint16_t EPOCH_YEAR = 1970; // Linux
const uint16_t EPOCH_YEAR = 2000;
//------------------------------------------------------------------------------
/** Count of days since Epoch.
* 1900 < EPOCH_YEAR, MAX_YEAR < 2100, (MAX_YEAR - EPOCH_YEAR) < 178.
* \param[in] y year (EPOCH_YEAR <= y <= MAX_YEAR)
* \param[in] m month 1 <= m <= 12
* \param[in] d day 1 <= d <= 31
* \return Count of days since epoch
*
* Derived from Zeller's congruence
*/
uint16_t daysSinceEpoch(uint16_t y, uint8_t m, uint8_t d) {
if (m < 3) {
m += 12;
y--;
}
return 365 * (y + 1 - EPOCH_YEAR) + y / 4 - (EPOCH_YEAR - 1) / 4
+ (153 * m - 2) / 5 + d - 398;
}
//------------------------------------------------------------------------------
/** Seconds since 1 Jan EPOCH_YEAR */
uint32_t secondsSinceEpoch(uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second) {
uint16_t days = daysSinceEpoch(year, month, day);
return second + 60L * (minute + 60L * (hour + 24L * days));
}
//------------------------------------------------------------------------------
void setup() {
uint32_t t[32];
Serial.begin(9600);
uint32_t m = micros();
for (uint8_t d = 1; d < 32; d++) {
t[d] = secondsSinceEpoch(2013, 8, d, 13, 50, 15);
}
m = micros() - m;
Serial.print("micros: ");
Serial.println(m);
for (uint8_t d = 1; d < 32; d++) {
Serial.println(t[d]);
}
}
//------------------------------------------------------------------------------
void loop() {}
And Time.h lib with your calculus above for seconds since epoch takes 40usecs:
40
1377857433
..
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
// year can be given as full four digit year or two digits (2010 or 10 for 2010);
// it is converted to years since 1970
if( yr > 99)
yr = yr - 1970;
else
yr += 30;
tm.Year = yr;
tm.Month = mnth;
tm.Day = dy;
tm.Hour = hr;
tm.Minute = min;
tm.Second = sec;
//setTime(makeTime(tm));
setTime(secondsSinceEpoch(tm.Year + 1970, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second));
}
PS: the conversion from RTC format to unix time must not be too frequent, as normally you run an internal systime (in unix format), and you do a sync with an external RTC from time to time only (Time.h does it in that way). An another conversion would be time consuming - when timestamping data with something like YYYY/MM/DD HH:MM:SS (a coversion from ux time to the human readable format).