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.
Dependencies: DipCortex-EEprom RTC flw mbed
RTC/ds3231m.cpp
- Committer:
- Backstrom
- Date:
- 2015-02-09
- Revision:
- 0:f6e68b4ce169
File content as of revision 0:f6e68b4ce169:
/*
* VFD Modular Clock - mbed
* (C) 2011-14 Akafugu Corporation
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
*/
#include "global.h"
#include "ds3231m.h"
#define DS3231M_SLAVE_ADDR 0xD0
DS3231M::DS3231M(I2C& i2c)
: RTC()
, m_i2c(i2c)
{
m_i2c.frequency(100000);
}
void DS3231M::begin()
{
}
time_t DS3231M::time()
{
return m_time;
}
struct tm* DS3231M::getTime()
{
char rtc[7];
rtc[0] = 0; // second register, 0
int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1);
int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 7);
// Clear clock halt bit from read data
//rtc[0] &= ~(_BV(CH_BIT));
m_tm.tm_sec = bcd2dec(rtc[0]);
m_tm.tm_min = bcd2dec(rtc[1]);
m_tm.tm_hour = bcd2dec(rtc[2]);
m_tm.tm_wday = bcd2dec(rtc[3])-1;
m_tm.tm_mday = bcd2dec(rtc[4]);
m_tm.tm_mon = bcd2dec(rtc[5])-1; // tm_mon is 0-11
m_tm.tm_year = bcd2dec(rtc[6]);
return &m_tm;
}
void DS3231M::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec)
{
char rtc[3];
rtc[0] = 0; // second register, 0
int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1);
int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 3);
// Clear clock halt bit from read data
//rtc[0] &= ~(_BV(CH_BIT));
if (sec) *sec = bcd2dec(rtc[0]);
if (min) *min = bcd2dec(rtc[1]);
if (hour) *hour = bcd2dec(rtc[2]);
}
void DS3231M::setTime(time_t t)
{
struct tm * timeinfo;
timeinfo = localtime (&t);
setTime(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
}
void DS3231M::setTime(uint8_t hour, uint8_t min, uint8_t sec)
{
write_byte(dec2bcd(sec), 0);
write_byte(dec2bcd(min), 1);
write_byte(dec2bcd(hour), 2);
}
void DS3231M::setTime(struct tm* tm)
{
write_byte(dec2bcd(tm->tm_sec), 0);
write_byte(dec2bcd(tm->tm_min), 1);
write_byte(dec2bcd(tm->tm_hour), 2);
write_byte(dec2bcd(tm->tm_wday+1), 3);
write_byte(dec2bcd(tm->tm_mday), 4);
write_byte(dec2bcd(tm->tm_mon+1), 5);
write_byte(dec2bcd(tm->tm_year), 6);
}
void DS3231M::setAlarm(time_t t)
{
struct tm * timeinfo;
timeinfo = localtime (&t);
setAlarm(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
}
void DS3231M::setAlarm(uint8_t hour, uint8_t min, uint8_t sec)
{
/*
* 07h: A1M1:0 Alarm 1 seconds
* 08h: A1M2:0 Alarm 1 minutes
* 09h: A1M3:0 Alarm 1 hour (bit6 is am/pm flag in 12h mode)
* 0ah: A1M4:1 Alarm 1 day/date (bit6: 1 for day, 0 for date)
* Sets alarm to fire when hour, minute and second matches
*/
write_byte(dec2bcd(sec), 0x07); // second
write_byte(dec2bcd(min), 0x08); // minute
write_byte(dec2bcd(hour), 0x09); // hour
write_byte(0x81, 0x0a); // day (upper bit must be set)
// clear alarm flag
uint8_t val = read_byte(0x0f);
write_byte(val & ~0x01, 0x0f);
}
struct tm* DS3231M::getAlarm(void)
{
struct tm * timeinfo = getTime();
uint8_t hour, min, sec;
getAlarm(&hour, &min, &sec);
timeinfo->tm_hour = hour;
timeinfo->tm_min = min;
timeinfo->tm_sec = sec;
return timeinfo;
}
void DS3231M::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec)
{
*sec = bcd2dec(read_byte(0x07) & ~0x80);
*min = bcd2dec(read_byte(0x08) & ~0x80);
*hour = bcd2dec(read_byte(0x09) & ~0x80);
}
bool DS3231M::checkAlarm(void)
{
// Alarm 1 flag (A1F) in bit 0
uint8_t val = read_byte(0x0f);
// clear flag when set
if (val & 1)
write_byte(val & ~0x01, 0x0f);
return val & 1 ? 1 : 0;
}
void DS3231M::SQWEnable(bool enable)
{
uint8_t control = read_byte(0x0E); // read control register
if (enable) {
control |= 0x40; // set BBSQW to 1
control &= ~0x04; // set INTCN to 0
}
else {
control &= ~0x40; // set BBSQW to 0
}
// write control back
write_byte(control, 0x0E);
}
void DS3231M::SQWSetFreq(enum RTC_SQW_FREQ freq)
{
uint8_t control = read_byte(0x0E); // read control register
control &= ~0x18; // Set to 0
control |= (freq << 4); // Set freq bitmask
// write control back
write_byte(control, 0x0E);
}
void DS3231M::Osc32kHzEnable(bool enable)
{
uint8_t status = read_byte(0x0F); // read status
if (enable)
status |= 0x08; // set to 1
else
status &= ~0x08; // Set to 0
// write status back
write_byte(status, 0x0F);
}
uint8_t DS3231M::read_byte(uint8_t offset)
{
char buf[1];
buf[0] = offset;
int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 1);
int r = m_i2c.read(DS3231M_SLAVE_ADDR, buf, 1);
//error = ((w!=0) || (r!=0));
return buf[0];
}
void DS3231M::write_byte(uint8_t b, uint8_t offset)
{
char buf[2];
buf[0] = offset;
buf[1] = b;
int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 2);
//error=(w!=0);
}
void DS3231M::write_addr(uint8_t addr)
{
/*
Wire.beginTransmission(RTC_ADDR);
Wire.write(addr);
Wire.endTransmission();
*/
}