ESPNTPServer/DS3231.cpp

232 lines
5.7 KiB
C++

/*
* DS3231.cpp
*
* Copyright 2017 Christopher B. Liebman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* Created on: May 21, 2017
* Author: chris.l
*/
#include "DS3231.h"
//#define DEBUG
#include "Logger.h"
DS3231::DS3231()
{
}
int DS3231::begin()
{
dbprintln("DS3231::begin()");
delay(2500); // DS3231 may need this on powerup.
uint8_t ctrl = 0b00000000; // enable osc/no BBS/no CONV/1hz/SQWV on/no ALRM
int err = write(DS3231_CONTROL_REG, ctrl); //CONTROL Register Address
if (err)
{
dbprintf("DS3231(): write(DS3231_CONTROL_REG) failed: %d\n", err);
return -1;
}
delay(100);
// set the clock to 24hr format
uint8_t hr;
if (read(DS3231_HOUR_REG, &hr))
{
dbprintf("DS3231::begin(): read(DS3231_HOUR_REG) failed!\n");
return -1;
}
// switch to 24hr mode if its not already
if (hr & _BV(DS3231_AMPM))
{
hr &= ~_BV(DS3231_AMPM);
if(write(DS3231_HOUR_REG, hr))
{
dbprintf("DS3231::begin(): write(DS3231_HOUR_REG, 0x%02x) failed!\n", hr);
return -1;
}
}
return 0;
}
uint8_t DS3231::fromBCD(uint8_t val)
{
return val - 6 * (val >> 4);
}
uint8_t DS3231::toBCD(uint8_t val)
{
return val + 6 * (val / 10);
}
int DS3231::readTime(DS3231DateTime& dt)
{
uint8_t count = setupRead(DS3231_SEC_REG, 7);
if (count != 7)
{
dbprintf("DS3231::readTime: setupRead failed! count:%u = 7\n", count);
Wire.clearWriteError();
Wire.flush();
return -1;
}
uint8_t seconds = Wire.read();
uint8_t minutes = Wire.read();
uint8_t hours = Wire.read();
uint8_t day = Wire.read();
uint8_t date = Wire.read();
uint8_t month = Wire.read();
uint8_t year = Wire.read();
dbprintf("DS3231::readTime raw month: 0x%02x\n", month);
dt.seconds = fromBCD(seconds);
dt.minutes = fromBCD(minutes);
dt.hours = fromBCD(hours & DS3231_24HR_MASK);
dt.day = fromBCD(day);
dt.date = fromBCD(date);
dt.month = fromBCD(month & DS3231_MONTH_MASK);
dt.year = fromBCD(year);
dt.century = month&DS3231_CENTURY? 1 : 0;
if (!dt.isValid())
{
dbprintf("DS3231::readTime: result not valid!!!\n");
Wire.clearWriteError();
Wire.flush();
return -1;
}
dbprintf("DS3231::readTime %04u-%02u-%02u %02u:%02u:%02u day:%u century:%u\n",
dt.year,
dt.month,
dt.date,
dt.hours,
dt.minutes,
dt.seconds,
dt.day,
dt.century);
return 0;
}
int DS3231::writeTime(DS3231DateTime &dt)
{
dbprintf("DS3231::writeTime %04u-%02u-%02u %02u:%02u:%02u day:%u century:%u\n",
dt.year,
dt.month,
dt.date,
dt.hours,
dt.minutes,
dt.seconds,
dt.day,
dt.century);
Wire.beginTransmission(DS3231_ADDRESS);
if (Wire.write(DS3231_SEC_REG) != 1)
{
Wire.endTransmission();
dbprintln("DS3231::writeTime: Wire.write(reg=DS3231_SEC_REG) failed!");
return -1;
}
int count;
count = Wire.write(toBCD(dt.seconds));
count += Wire.write(toBCD(dt.minutes));
count += Wire.write(toBCD(dt.hours));
count += Wire.write(toBCD(dt.day));
count += Wire.write(toBCD(dt.date));
count += Wire.write(toBCD(dt.month) | (dt.century ? _BV(DS3231_CENTURY) : 0));
count += Wire.write(toBCD(dt.year));
if (count != 7)
{
dbprintf("DS3231::writeTime: Wire.write() all fields, expected 7 got %u\n", count);
return -1;
}
int err = Wire.endTransmission();
if (err)
{
dbprintf("DS3231::writeTime: Wire.endTransmission() returned: %d\n", err);
return -1;
}
return(0);
}
int DS3231::setupRead(uint8_t reg, uint8_t size)
{
Wire.beginTransmission(DS3231_ADDRESS);
if (Wire.write(reg) != 1)
{
Wire.endTransmission();
dbprintln("DS3231::setupRead: Wire.write(DS3231_CONTROL_REG) failed!");
return -1;
}
int err = Wire.endTransmission();
if (err)
{
dbprintf("DS3231::setupRead: Wire.endTransmission() returned: %d\n", err);
return -1;
}
return Wire.requestFrom(DS3231_ADDRESS, (size_t)size);
}
int DS3231::read(uint8_t reg, uint8_t *value)
{
size_t count = setupRead(reg, 1);
count = Wire.requestFrom(DS3231_ADDRESS, (size_t)1);
*value = Wire.read();
if (count != 1)
{
dbprintf("DS3231::read: Wire.requestFrom() returns %u, expected 1\n", count);
return -1;
}
return 0;
}
int DS3231::write(uint8_t reg, uint8_t value)
{
Wire.beginTransmission(DS3231_ADDRESS);
if (Wire.write(reg) != 1)
{
Wire.endTransmission();
dbprintf("DS3231::write: Wire.write(reg=%d, value=%d) failed!\n", reg, value);
return -1;
}
size_t count;
count = Wire.write(value);
if (count != 1)
{
dbprintf("DS3231::write: Wire.write(value=%u) returns %u\n", value, count);
return -1;
}
int err = Wire.endTransmission();
if (err)
{
dbprintf("DS3231::write: Wire.endTransmission() returned: %d\n", err);
return -1;
}
return(0);
}