Initial addition of RTC code -- debugging enabled due to this code being untested
This commit is contained in:
parent
22a462911c
commit
4a60bf7477
|
@ -11,7 +11,7 @@
|
|||
#ifndef Project_h
|
||||
#define Project_h
|
||||
|
||||
#define DEBUG false // For controlling debug output via serial
|
||||
#define DEBUG true // For controlling debug output via serial
|
||||
|
||||
// Buttons / Joystick / Input Hardware Pinouts
|
||||
#define okButtonPin 22
|
||||
|
|
240
Universal_Serial_Adapter/RTClib.cpp
Normal file
240
Universal_Serial_Adapter/RTClib.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
// Code by JeeLabs http://news.jeelabs.org/code/
|
||||
// Released to the public domain! Enjoy!
|
||||
|
||||
#include <Wire.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "RTClib.h"
|
||||
|
||||
#define DS1307_ADDRESS 0x68
|
||||
#define SECONDS_PER_DAY 86400L
|
||||
|
||||
#define SECONDS_FROM_1970_TO_2000 946684800
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include <Arduino.h> // capital A so it is error prone on case-sensitive filesystems
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
int i = 0; //The new wire library needs to take an int when you are sending for the zero register
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// utility code, some of this could be exposed in the DateTime API if needed
|
||||
|
||||
const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //has to be const or compiler compaints
|
||||
|
||||
// number of days since 2000/01/01, valid for 2001..2099
|
||||
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
|
||||
if (y >= 2000)
|
||||
y -= 2000;
|
||||
uint16_t days = d;
|
||||
for (uint8_t i = 1; i < m; ++i)
|
||||
days += pgm_read_byte(daysInMonth + i - 1);
|
||||
if (m > 2 && y % 4 == 0)
|
||||
++days;
|
||||
return days + 365 * y + (y + 3) / 4 - 1;
|
||||
}
|
||||
|
||||
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
|
||||
return ((days * 24L + h) * 60 + m) * 60 + s;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DateTime implementation - ignores time zones and DST changes
|
||||
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
|
||||
|
||||
DateTime::DateTime (uint32_t t) {
|
||||
t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
|
||||
|
||||
ss = t % 60;
|
||||
t /= 60;
|
||||
mm = t % 60;
|
||||
t /= 60;
|
||||
hh = t % 24;
|
||||
uint16_t days = t / 24;
|
||||
uint8_t leap;
|
||||
for (yOff = 0; ; ++yOff) {
|
||||
leap = yOff % 4 == 0;
|
||||
if (days < 365 + leap)
|
||||
break;
|
||||
days -= 365 + leap;
|
||||
}
|
||||
for (m = 1; ; ++m) {
|
||||
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
|
||||
if (leap && m == 2)
|
||||
++daysPerMonth;
|
||||
if (days < daysPerMonth)
|
||||
break;
|
||||
days -= daysPerMonth;
|
||||
}
|
||||
d = days + 1;
|
||||
}
|
||||
|
||||
DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
|
||||
if (year >= 2000)
|
||||
year -= 2000;
|
||||
yOff = year;
|
||||
m = month;
|
||||
d = day;
|
||||
hh = hour;
|
||||
mm = min;
|
||||
ss = sec;
|
||||
}
|
||||
|
||||
static uint8_t conv2d(const char* p) {
|
||||
uint8_t v = 0;
|
||||
if ('0' <= *p && *p <= '9')
|
||||
v = *p - '0';
|
||||
return 10 * v + *++p - '0';
|
||||
}
|
||||
|
||||
// A convenient constructor for using "the compiler's time":
|
||||
// DateTime now (__DATE__, __TIME__);
|
||||
// NOTE: using PSTR would further reduce the RAM footprint
|
||||
DateTime::DateTime (const char* date, const char* time) {
|
||||
// sample input: date = "Dec 26 2009", time = "12:34:56"
|
||||
yOff = conv2d(date + 9);
|
||||
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
||||
switch (date[0]) {
|
||||
case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
|
||||
case 'F': m = 2; break;
|
||||
case 'A': m = date[2] == 'r' ? 4 : 8; break;
|
||||
case 'M': m = date[2] == 'r' ? 3 : 5; break;
|
||||
case 'S': m = 9; break;
|
||||
case 'O': m = 10; break;
|
||||
case 'N': m = 11; break;
|
||||
case 'D': m = 12; break;
|
||||
}
|
||||
d = conv2d(date + 4);
|
||||
hh = conv2d(time);
|
||||
mm = conv2d(time + 3);
|
||||
ss = conv2d(time + 6);
|
||||
}
|
||||
|
||||
uint8_t DateTime::dayOfWeek() const {
|
||||
uint16_t day = date2days(yOff, m, d);
|
||||
return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
|
||||
}
|
||||
|
||||
uint32_t DateTime::unixtime(void) const {
|
||||
uint32_t t;
|
||||
uint16_t days = date2days(yOff, m, d);
|
||||
t = time2long(days, hh, mm, ss);
|
||||
t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RTC_DS1307 implementation
|
||||
|
||||
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
|
||||
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
|
||||
|
||||
uint8_t RTC_DS1307::begin(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
|
||||
uint8_t RTC_DS1307::isrunning(void) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(i);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 1);
|
||||
uint8_t ss = Wire.read();
|
||||
return !(ss>>7);
|
||||
}
|
||||
|
||||
void RTC_DS1307::adjust(const DateTime& dt) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(i);
|
||||
Wire.write(bin2bcd(dt.second()));
|
||||
Wire.write(bin2bcd(dt.minute()));
|
||||
Wire.write(bin2bcd(dt.hour()));
|
||||
Wire.write(bin2bcd(0));
|
||||
Wire.write(bin2bcd(dt.day()));
|
||||
Wire.write(bin2bcd(dt.month()));
|
||||
Wire.write(bin2bcd(dt.year() - 2000));
|
||||
Wire.write(i);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
DateTime RTC_DS1307::now() {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(i);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 7);
|
||||
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
|
||||
uint8_t mm = bcd2bin(Wire.read());
|
||||
uint8_t hh = bcd2bin(Wire.read());
|
||||
Wire.read();
|
||||
uint8_t d = bcd2bin(Wire.read());
|
||||
uint8_t m = bcd2bin(Wire.read());
|
||||
uint16_t y = bcd2bin(Wire.read()) + 2000;
|
||||
|
||||
return DateTime (y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint8_t RTC_DS1307::isrunning(void) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.send(i);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 1);
|
||||
uint8_t ss = Wire.receive();
|
||||
return !(ss>>7);
|
||||
}
|
||||
|
||||
void RTC_DS1307::adjust(const DateTime& dt) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.send(i);
|
||||
Wire.send(bin2bcd(dt.second()));
|
||||
Wire.send(bin2bcd(dt.minute()));
|
||||
Wire.send(bin2bcd(dt.hour()));
|
||||
Wire.send(bin2bcd(0));
|
||||
Wire.send(bin2bcd(dt.day()));
|
||||
Wire.send(bin2bcd(dt.month()));
|
||||
Wire.send(bin2bcd(dt.year() - 2000));
|
||||
Wire.send(i);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
DateTime RTC_DS1307::now() {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.send(i);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 7);
|
||||
uint8_t ss = bcd2bin(Wire.receive() & 0x7F);
|
||||
uint8_t mm = bcd2bin(Wire.receive());
|
||||
uint8_t hh = bcd2bin(Wire.receive());
|
||||
Wire.receive();
|
||||
uint8_t d = bcd2bin(Wire.receive());
|
||||
uint8_t m = bcd2bin(Wire.receive());
|
||||
uint16_t y = bcd2bin(Wire.receive()) + 2000;
|
||||
|
||||
return DateTime (y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RTC_Millis implementation
|
||||
|
||||
long RTC_Millis::offset = 0;
|
||||
|
||||
void RTC_Millis::adjust(const DateTime& dt) {
|
||||
offset = dt.unixtime() - millis() / 1000;
|
||||
}
|
||||
|
||||
DateTime RTC_Millis::now() {
|
||||
return (uint32_t)(offset + millis() / 1000);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
47
Universal_Serial_Adapter/RTClib.h
Normal file
47
Universal_Serial_Adapter/RTClib.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Code by JeeLabs http://news.jeelabs.org/code/
|
||||
// Released to the public domain! Enjoy!
|
||||
|
||||
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
|
||||
class DateTime {
|
||||
public:
|
||||
DateTime (uint32_t t =0);
|
||||
DateTime (uint16_t year, uint8_t month, uint8_t day,
|
||||
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
|
||||
DateTime (const char* date, const char* time);
|
||||
uint16_t year() const { return 2000 + yOff; }
|
||||
uint8_t month() const { return m; }
|
||||
uint8_t day() const { return d; }
|
||||
uint8_t hour() const { return hh; }
|
||||
uint8_t minute() const { return mm; }
|
||||
uint8_t second() const { return ss; }
|
||||
uint8_t dayOfWeek() const;
|
||||
|
||||
// 32-bit times as seconds since 1/1/2000
|
||||
long secondstime() const;
|
||||
// 32-bit times as seconds since 1/1/1970
|
||||
uint32_t unixtime(void) const;
|
||||
|
||||
protected:
|
||||
uint8_t yOff, m, d, hh, mm, ss;
|
||||
};
|
||||
|
||||
// RTC based on the DS1307 chip connected via I2C and the Wire library
|
||||
class RTC_DS1307 {
|
||||
public:
|
||||
static uint8_t begin(void);
|
||||
static void adjust(const DateTime& dt);
|
||||
uint8_t isrunning(void);
|
||||
static DateTime now();
|
||||
};
|
||||
|
||||
// RTC using the internal millis() clock, has to be initialized before use
|
||||
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
|
||||
class RTC_Millis {
|
||||
public:
|
||||
static void begin(const DateTime& dt) { adjust(dt); }
|
||||
static void adjust(const DateTime& dt);
|
||||
static DateTime now();
|
||||
|
||||
protected:
|
||||
static long offset;
|
||||
};
|
|
@ -8,7 +8,7 @@
|
|||
attribute.
|
||||
*/
|
||||
|
||||
#include <Metro.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "Project.h"
|
||||
#include "Config.h"
|
||||
|
@ -26,6 +26,7 @@
|
|||
|
||||
UI* ui;
|
||||
Config* config;
|
||||
RTC_DS1307 rtc;
|
||||
|
||||
// helper for interrupt method call
|
||||
void processSerial() {
|
||||
|
@ -33,11 +34,26 @@ void processSerial() {
|
|||
}
|
||||
|
||||
void setup() {
|
||||
// Setup various IO busses
|
||||
Serial.begin(115200);
|
||||
Wire.begin();
|
||||
|
||||
// Ensure RTC is set to run on battery
|
||||
// clear /EOSC bit
|
||||
// Sometimes necessary to ensure that the clock
|
||||
// keeps running on just battery power. Once set,
|
||||
// it shouldn't need to be reset but it's a good
|
||||
// idea to make sure.
|
||||
Wire.beginTransmission(0x68); // address DS3231
|
||||
Wire.write(0x0E); // select register
|
||||
Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
|
||||
Wire.endTransmission();
|
||||
|
||||
rtc.begin();
|
||||
|
||||
// Stuff used for serial and UI
|
||||
config = new Config();
|
||||
config->setDefaults();
|
||||
|
||||
ui = new UI();
|
||||
|
||||
// Setup serial IO on an interrupt timer
|
||||
|
@ -48,6 +64,22 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
if (DEBUG) {
|
||||
DateTime now = RTC.now();
|
||||
Serial.print(now.year(), DEC);
|
||||
Serial.print('/');
|
||||
Serial.print(now.month(), DEC);
|
||||
Serial.print('/');
|
||||
Serial.print(now.day(), DEC);
|
||||
Serial.print(' ');
|
||||
Serial.print(now.hour(), DEC);
|
||||
Serial.print(':');
|
||||
Serial.print(now.minute(), DEC);
|
||||
Serial.print(':');
|
||||
Serial.print(now.second(), DEC);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Serial data is processed via an interrupt so isn't needed in the main loop
|
||||
ui->processInputEvents();
|
||||
ui->processTimeoutEvents();
|
||||
|
|
Reference in a new issue