diff --git a/Arduino/BTCDieselHeater/BTCDateTime.cpp b/Arduino/BTCDieselHeater/BTCDateTime.cpp new file mode 100644 index 0000000..049c61a --- /dev/null +++ b/Arduino/BTCDieselHeater/BTCDateTime.cpp @@ -0,0 +1,124 @@ +#include "BTCDateTime.h" +#include "helpers.h" + +const char* +BTCDateTime::dowStr() const +{ + return daysOfTheWeek[dayOfTheWeek()]; +} + +const char* +BTCDateTime::monthStr() const +{ + return months[month()-1]; +} + +BTCDateTime& +BTCDateTime::operator=(const DateTime& rhs) +{ + yOff = rhs.year()-2000; + m = rhs.month(); + d = rhs.day(); + hh = rhs.hour(); + mm = rhs.minute(); + ss = rhs.second(); +} + +BTCDateTime& +BTCDateTime::operator=(const BTCDateTime& rhs) +{ + yOff = rhs.yOff; + m = rhs.m; + d = rhs.d; + hh = rhs.hh; + mm = rhs.mm; + ss = rhs.ss; +} + +void +BTCDateTime::adjustDay(int dir) +{ + int days = daysInMonth(m, yOff); + if(dir > 0) { + if(d == days) d = 1; + else d++; + } + else { + if(d == 1) d = days; + else d--; + } +} + +void +BTCDateTime::adjustMonth(int dir) +{ + if(dir > 0) { + if(m == 12) m = 1; + else m++; + } + else { + if(m == 1) m = 12; + else m--; + } + int days = daysInMonth(m, yOff); // trap shorter months + UPPERLIMIT(d, days); +} + +void +BTCDateTime::adjustYear(int dir) +{ + yOff += dir; + int days = daysInMonth(m, yOff); + UPPERLIMIT(d, days); // pick up 29 Feb +} + +void +BTCDateTime::adjustHour(int dir) +{ + if(dir > 0) { + if(hh == 23) hh = 0; + else hh++; + } + else { + if(hh == 0) hh = 23; + else hh--; + } +} + +void +BTCDateTime::adjustMinute(int dir) +{ + if(dir > 0) { + if(mm == 59) mm = 0; + else mm++; + } + else { + if(mm == 0) mm = 59; + else mm--; + } +} + +void +BTCDateTime::adjustSecond(int dir) +{ + if(dir > 0) { + if(ss == 59) ss = 0; + else ss++; + } + else { + if(ss == 0) ss = 59; + else ss--; + } +} + +int +BTCDateTime::daysInMonth(int month, int year) +{ + if(month >= 1 && month <= 12) { + int days = monthDays[month-1]; + if((month == 2) && ((year & 0x03) == 0)) + days++; + return days; + } + return -1; +} diff --git a/Arduino/BTCDieselHeater/BTCDateTime.h b/Arduino/BTCDieselHeater/BTCDateTime.h new file mode 100644 index 0000000..e606bda --- /dev/null +++ b/Arduino/BTCDieselHeater/BTCDateTime.h @@ -0,0 +1,25 @@ +#ifndef __BTCDATETIME_H__ +#define __BTCDATETIME_H__ + +#include "RTClib.h" + +class BTCDateTime : public DateTime { + const char daysOfTheWeek[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + const char months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + const char monthDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +public: + const char* monthStr() const; + const char* dowStr() const; + const char* briefDowStr() const; + int daysInMonth(int month, int year); + void adjustDay(int val); + void adjustMonth(int val); + void adjustYear(int dir); + void adjustHour(int dir); + void adjustMinute(int dir); + void adjustSecond(int dir); + BTCDateTime& operator=(const DateTime& rhs); + BTCDateTime& operator=(const BTCDateTime& rhs); +}; + +#endif // __BTCDATETIME_H__ diff --git a/Arduino/BTCDieselHeater/Clock.cpp b/Arduino/BTCDieselHeater/Clock.cpp new file mode 100644 index 0000000..c2667c2 --- /dev/null +++ b/Arduino/BTCDieselHeater/Clock.cpp @@ -0,0 +1,93 @@ +#include +#include "Clock.h" +#include "BTCDateTime.h" +#include "Wire.h" +#include "RTClib.h" +#include "helpers.h" +#include "NVStorage.h" + +CClock::CClock(RTC_DS3231& rtc) : _rtc(rtc) +{ +} + +void +CClock::begin() +{ + _rtc.begin(); + _nextRTCfetch = millis(); +} + +const BTCDateTime& +CClock::update() +{ + long deltaT = millis() - _nextRTCfetch; + if(deltaT >= 0) { + uint32_t origClock = Wire.getClock(); + Wire.setClock(400000); + _currentTime = _rtc.now(); // moderate I2C accesses + Wire.setClock(origClock); + _nextRTCfetch = millis() + 500; + _checkTimers(); + } + return _currentTime; +} + +const BTCDateTime& +CClock::get() const +{ + return _currentTime; +} + +void +CClock::set(const DateTime& newTimeDate) +{ + _rtc.adjust(newTimeDate); +} + +void +CClock::_checkTimers() +{ + _checkTimer(0, _currentTime); // test timer 1 + _checkTimer(1, _currentTime); // test timer 2 +} + +void +CClock::_checkTimer(int timer, const DateTime& now) +{ + sTimer Info; + NVstore.getTimerInfo(timer, Info); + int DOW = now.dayOfTheWeek(); + int timeNow = now.hour() * 60 + now.minute(); + int timeStart = Info.start.hour * 60 + Info.start.min; + int timeStop = Info.stop.hour * 60 + Info.stop.min; + + // ensure DOW tracks expected start day should timer straddle midnight + if(timeStop < timeStart) { // true if stop is next morning + if(timeNow <= timeStop) { // current time has passed midnight - enable flag is based upon prior day + DOW--; + ROLLLOWERLIMIT(DOW, 0, 6); // fixup for saturday night! + } + } + // DOW of week is now correct for the day this timer started + int maskDOW = 0x01 << DOW; + + if(Info.enabled & (maskDOW | 0x80) ) { // specific day of week, or next day + + if(timeNow == timeStart && now.second() < 3) { // check start, within 2 seconds of the minute rollover + requestOn(); + } + + if(timeNow == timeStop) { // check stop + requestOff(); + if(!Info.repeat) { // cancel timer if non repeating + if(Info.enabled & 0x80) // next day start flag set? + Info.enabled = 0; // outright cancel + else { + Info.enabled &= ~maskDOW; // otherwise clear specific day + } + NVstore.setTimerInfo(timer, Info); + NVstore.save(); + } + } + } +} diff --git a/Arduino/BTCDieselHeater/Clock.h b/Arduino/BTCDieselHeater/Clock.h new file mode 100644 index 0000000..c4c295c --- /dev/null +++ b/Arduino/BTCDieselHeater/Clock.h @@ -0,0 +1,30 @@ +#ifndef __BTC_TIMERS_H__ +#define __BTC_TIMERS_H__ + +#include "BTCDateTime.h" + +/*const BTCDateTime& getCurrentTime(); +void setCurrentTime(const DateTime& newDateTime); + +void initClock(); +void checkClock();*/ + +class CClock { + + RTC_DS3231& _rtc; + unsigned long _nextRTCfetch; + BTCDateTime _currentTime; + + void _checkTimers(); + void _checkTimer(int timer, const DateTime& now); +public: + CClock(RTC_DS3231& rtc); + void begin(); + const BTCDateTime& update(); + const BTCDateTime& get() const; + void set(const DateTime& newTime); +}; + +extern CClock Clock; + +#endif // __BTC_TIMERS_H__ diff --git a/Arduino/BTCDieselHeater/Screen8.cpp b/Arduino/BTCDieselHeater/Screen8.cpp new file mode 100644 index 0000000..9edfe7b --- /dev/null +++ b/Arduino/BTCDieselHeater/Screen8.cpp @@ -0,0 +1,93 @@ +/* + * This file is part of the "bluetoothheater" distribution + * (https://gitlab.com/mrjones.id.au/bluetoothheater) + * + * Copyright (C) 2018 Ray Jones + * + * 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 3 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "128x64OLED.h" +#include "KeyPad.h" +#include "helpers.h" +#include "Screen8.h" +#include "Tahoma16.h" +#include "Clock.h" + +/////////////////////////////////////////////////////////////////////////// +// +// CScreen8 +// +// This screen presents a large format clock +// +/////////////////////////////////////////////////////////////////////////// + + +CScreen8::CScreen8(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr) +{ + _colon = false; +} + +void +CScreen8::showTime(int) +{ + // override and DO NOTHING! +} + + +void +CScreen8::show() +{ + CScreenHeader::show(); + + const BTCDateTime& now = Clock.get(); + + char str[32]; +// if(now.second() & 0x01) + if(_colon) + sprintf(str, "%d:%02d", now.hour(), now.minute()); + else + sprintf(str, "%d %02d", now.hour(), now.minute()); + _colon = !_colon; + + int yPos = 25; + { + CTransientFont AF(_display, &tahoma_16ptFontInfo); // temporarily use a large font + _printMenuText(_display.xCentre(), yPos, str, false, eCentreJustify); + } + sprintf(str, "%s %d %s %d", now.dowStr(), now.day(), now.monthStr(), now.year()); + _printMenuText(_display.xCentre(), 56, str, false, eCentreJustify); +} + + +void +CScreen8::keyHandler(uint8_t event) +{ + if(event & keyPressed) { + // press CENTRE + if(event & key_Centre) { + return; + } + // press LEFT + if(event & key_Left) { + _ScreenManager.prevScreen(); + } + // press RIGHT + if(event & key_Right) { + _ScreenManager.nextScreen(); + } + } +} + diff --git a/Arduino/BTCDieselHeater/Screen8.h b/Arduino/BTCDieselHeater/Screen8.h new file mode 100644 index 0000000..d988bd1 --- /dev/null +++ b/Arduino/BTCDieselHeater/Screen8.h @@ -0,0 +1,36 @@ +/* + * This file is part of the "bluetoothheater" distribution + * (https://gitlab.com/mrjones.id.au/bluetoothheater) + * + * Copyright (C) 2018 Ray Jones + * + * 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 3 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "stdint.h" +#include "ScreenHeader.h" + +class C128x64_OLED; +class CScreenManager; + +class CScreen8 : public CScreenHeader { +protected: + virtual void showTime(int numTimers); + bool _colon; +public: + CScreen8(C128x64_OLED& display, CScreenManager& mgr); + void show(); + void keyHandler(uint8_t event); +};