Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RTclock.cpp
- Committer:
- vtraveller
- Date:
- 2014-10-08
- Revision:
- 15:1645f55bd0ee
- Parent:
- 14:d5b47ff12d17
- Child:
- 16:f7e4b4cbfb9e
File content as of revision 15:1645f55bd0ee:
#include "mbed.h"
#include "RTclock.h"
RTclock::RTclock(I2C & in_cI2C, uint8_t in_nAddress, EClockType in_eClockType)
: m_bTwelveHour(false)
, m_cI2C(in_cI2C)
, m_nAddress(in_nAddress)
, m_eClockType(in_eClockType)
{
}
RTclock::~RTclock()
{
}
int RTclock::bcdToDecimal(int in_nBCD)
{
return ((in_nBCD & 0xF0) >> 4) * 10 + (in_nBCD & 0x0F);
}
int RTclock::decimalToBcd(int in_nDecimal)
{
return (in_nDecimal % 10) + ((in_nDecimal / 10) << 4);
}
bool RTclock::getTime(tm & out_sTM)
{
char aBuffer[7];
if (!read(0, aBuffer, 7)) return false;
m_bTwelveHour = ((aBuffer[2] & 0x40) == 0x40);
out_sTM.tm_sec = bcdToDecimal(aBuffer[0] & 0x7f);
out_sTM.tm_min = bcdToDecimal(aBuffer[1]);
if (m_bTwelveHour)
{
// add 12 hours if PM bit is set and past midday
out_sTM.tm_hour = bcdToDecimal(aBuffer[2] & 0x1f);
bool bPM = (0 != (aBuffer[2] & 0x20));
if (bPM && 12 != out_sTM.tm_hour) out_sTM.tm_hour += 12;
}
else
{
out_sTM.tm_hour = bcdToDecimal(aBuffer[2] & 0x3f);
}
out_sTM.tm_wday = aBuffer[3] % 7;
out_sTM.tm_mday = bcdToDecimal(aBuffer[4]);
out_sTM.tm_mon = bcdToDecimal(aBuffer[5]);
out_sTM.tm_year = (bcdToDecimal(aBuffer[6]) + 2000) - 1900; // Returns from 2000, need form 1900 for time function
out_sTM.tm_isdst = 0;
return true;
}
bool RTclock::isTwelveHour()
{
return m_bTwelveHour;
}
bool RTclock::mapTime()
{
tm sTM;
if (!getTime(sTM)) return false;
// Convert and set internal time
time_t nTime = ::mktime(&sTM);
::set_time(nTime);
return true;
}
bool RTclock::read(uint8_t in_nAddress, char * out_pBuffer, int in_nLength)
{
if (0 != m_cI2C.write(m_nAddress, (char *)&in_nAddress, 1)) return false;
if (0 != m_cI2C.read(m_nAddress, out_pBuffer, in_nLength)) return false;
return true;
}
bool RTclock::setTime(const tm & in_sTM, bool in_bTwelveHour)
{
char aBuffer[7];
// Preserve flags that were in register
if (!read(0,aBuffer,7)) return false;
m_bTwelveHour = in_bTwelveHour;
// We always have tm in 24hr form - so adjut if 12hr clock
int nHour = in_sTM.tm_hour;
if (in_bTwelveHour) nHour %= 12;
switch (m_eClockType)
{
case eDS1311:
aBuffer[0] &= 0x7f;
aBuffer[0] = (aBuffer[0] & 0x80) | (decimalToBcd(in_sTM.tm_sec)& 0x7f);
aBuffer[1] = decimalToBcd(in_sTM.tm_min);
aBuffer[2] = (aBuffer[2] & 0xc4) | (decimalToBcd(nHour) & 0x3f);
aBuffer[3] = in_sTM.tm_wday;
aBuffer[4] = decimalToBcd(in_sTM.tm_mday);
aBuffer[5] = decimalToBcd(in_sTM.tm_mon);
aBuffer[6] = decimalToBcd(in_sTM.tm_year + 1900 - 2000);
// Handle the 12hr clock bits
if (in_bTwelveHour)
{
// Turn on 12hr clock
aBuffer[2] |= 0x40;
// Set am/pm bit based on hours
if (in_sTM.tm_hour >= 12) aBuffer[2] |= 0x20; else aBuffer[2] &= ~0x20;
}
else
{
aBuffer[2] &= ~64;
}
break;
case eDS3231:
aBuffer[0] = decimalToBcd(in_sTM.tm_sec) & 0x7f;
aBuffer[1] = decimalToBcd(in_sTM.tm_min) & 0x7f;
aBuffer[2] = decimalToBcd(nHour) & (m_bTwelveHour ? 0x1f : 0x3f);
aBuffer[3] = in_sTM.tm_wday;
aBuffer[4] = decimalToBcd(in_sTM.tm_mday);
aBuffer[5] = decimalToBcd(in_sTM.tm_mon) & ~0x80 /* 2000+ */;
aBuffer[6] = decimalToBcd(in_sTM.tm_year + 1900 - 2000);
// Handle the 12hr clock bits
if (in_bTwelveHour)
{
// Turn on 12hr clock
aBuffer[2] |= 0x40;
// Set am/pm bit based on hours
if (in_sTM.tm_hour >= 12) aBuffer[2] |= 0x20;
}
break;
}
// Write new date and time
setRunning(false);
bool bSuccess = write(0, aBuffer, 7);
if (bSuccess) setRunning(true);
return bSuccess;
}
bool RTclock::setRunning(bool in_bEnable)
{
char nRunning;
if (!read(0, &nRunning, 1)) return false;
// Set running
if (in_bEnable)
{
nRunning &= 0x7F;
}
else
{
nRunning |= 0x80;
}
return write(0, &nRunning, 1);
}
bool RTclock::setSquareWaveOutput
(
bool in_bEnable,
ESquareWaveRates in_nRateSelect
)
{
char nValue;
// Read register
if (!read(7, &nValue, 1)) return false;
// Protect control bits
nValue = (nValue & 0x80) | (in_bEnable ? 0x10 : 0) | ((char)in_nRateSelect & 0x03);
return write(7, &nValue, 1);
}
bool RTclock::write(uint8_t in_nAddress, const char * in_pBuffer, int in_nLength)
{
char aBuffer[10];
aBuffer[0] = in_nAddress & 0xff;
for (size_t i = 0 ; i < in_nLength; i++)
aBuffer[i + 1] = in_pBuffer[i];
return m_cI2C.write(m_nAddress, aBuffer, in_nLength + 1);
}