/elec/propeller-clock

To get this branch, use:
bzr branch http://bzr.ed.am/elec/propeller-clock
58 by edam
removed Bounce library and updated/fixed new code
1
/*
2
 * time.cc
3
 *
4
 * Copyright (C) 2011 Tim Marston <tim@ed.am> and Dan Marston.
5
 *
6
 * This file is part of propeller-clock (hereafter referred to as "this
7
 * program"). See http://ed.am/dev/software/arduino/propeller-clock for more
8
 * information.
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Lesser General Public License as published
12
 * by the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
56 by edam
updated software to include drawing abstraction infrastructure
23
#include "time.h"
24
#include <DS1307.h>
25
#include <Wire.h>
26
27
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
28
#define YEAR_MAX 2030
91 by Tim Marston
fixed text glitch; extended all modes; added screen flip super-long press;
29
#define YEAR_MIN 2012
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
30
31
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
32
// year
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
33
static int _year = 2012;
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
34
35
// month
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
36
static int _month = 5;
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
37
38
// day
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
39
static int _day = 18;
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
40
41
// hours
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
42
static int _hours = 15;
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
43
44
// minutes
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
45
static int _minutes = 36;
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
46
47
// seconds
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
48
static int _seconds = 0;
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
49
50
// milliseconds at last update
51
static unsigned long _last_millis = millis();
52
53
// milliseconds carries over from last update
54
static unsigned long _carry = 0;
55
56
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
57
static int days_in_month( int month, int year )
58
{
59
	if( month == 2 )
60
		return !( year % 4 ) && ( ( year % 100 ) || !( year % 400 ) )? 29 : 28;
61
	else if( month == 9 || month == 6 || month == 4 || month == 11 )
62
		return 30;
63
	else
64
		return 31;
65
}
66
67
68
void Time::load_time()
69
{
70
	// get the time from the real-time clock
71
	int rtc_data[ 7 ];
72
	RTC.get( rtc_data, true );
73
	_year = rtc_data[ DS1307_YR ];
74
	_month = rtc_data[ DS1307_MTH ];
75
	_day = rtc_data[ DS1307_DAY ];
76
	_hours = rtc_data[ DS1307_HR ];
77
	_minutes = rtc_data[ DS1307_MIN ];
78
	_seconds = rtc_data[ DS1307_SEC ];
79
80
	// make sure some numbers are in range
91 by Tim Marston
fixed text glitch; extended all modes; added screen flip super-long press;
81
	if( _year < YEAR_MIN || _year > YEAR_MAX ) _year = YEAR_MIN;
89 by Tim Marston
moved rount Time a bit, and passed _button to SettingsMajorMode so that it can
82
	if( _month < 1 || _month > 12 ) _month = 1;
83
	if( _day < 1 || _day > days_in_month( _year, _month ) ) _day = 1;
84
}
85
86
87
void Time::save_time()
88
{
89
	// set the time on the real-time clock
90
	RTC.stop();
91
	RTC.set( DS1307_YR, _year );
92
	RTC.set( DS1307_MTH, _month );
93
	RTC.set( DS1307_DAY, _day );
94
	RTC.set( DS1307_HR, _hours );
95
	RTC.set( DS1307_MIN, _minutes );
96
	RTC.set( DS1307_SEC, _seconds );
97
	RTC.start();
98
}
99
56 by edam
updated software to include drawing abstraction infrastructure
100
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
101
int Time::get_year()
102
{
103
	return _year;
104
}
105
106
107
int Time::get_month()
108
{
109
	return _month;
110
}
111
112
113
const char *Time::get_month_name()
114
{
115
	static const char *months[] = {
116
		"January",
117
		"February",
118
		"March",
119
		"April",
120
		"May",
121
		"June",
122
		"July",
123
		"August",
124
		"September",
125
		"October",
126
		"November",
127
		"December",
128
	};
129
130
	return months[ _month - 1 ];
131
}
132
133
134
int Time::get_day()
135
{
136
	return _day;
137
}
138
139
140
const char *Time::get_day_suffix()
141
{
142
	switch( _day )
143
	{
144
	case 1:
145
	case 21:
146
	case 31:
147
		return "st";
148
	case 2:
149
	case 22:
150
		return "nd";
151
	case 3:
152
	case 23:
153
		return "rd";
154
	default:
155
		return "th";
156
	}
157
}
158
159
56 by edam
updated software to include drawing abstraction infrastructure
160
int Time::get_hours()
161
{
162
	return _hours;
163
}
164
165
166
int Time::get_minutes()
167
{
168
	return _minutes;
169
}
170
171
172
int Time::get_seconds()
173
{
174
	return _seconds;
175
}
176
177
178
void Time::update()
179
{
68 by Tim Marston
added frame reset code and inited minor mode flavours on mode activation
180
	// how many milliseconds have elapsed since we last checked?
56 by edam
updated software to include drawing abstraction infrastructure
181
	unsigned long millis = ::millis();
182
	unsigned long delta = millis - _last_millis + _carry;
183
184
	// update the previous time and carried-over milliseconds
185
	_last_millis = millis;
186
	_carry = delta % 1000;
187
188
	// add the seconds that have passed to the time
189
	_seconds += delta / 1000;
190
	while( _seconds >= 60 ) {
191
		_seconds -= 60;
192
		_minutes++;
193
		if( _minutes >= 60 ) {
194
			_minutes -= 60;
195
			_hours++;
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
196
			if( _hours >= 24 ) {
56 by edam
updated software to include drawing abstraction infrastructure
197
				_hours -= 24;
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
198
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
199
				// We *could* manually work out the day here... but we might as
200
				// well ask the RTC hardware. We can't do this *all* the time
201
				// though, because it isn't fast enough and will actually cause
202
				// a minor display glitch.
203
				load_time();
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
204
			}
56 by edam
updated software to include drawing abstraction infrastructure
205
		}
206
	}
207
}
208
209
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
210
void Time::inc_hours()
211
{
212
	if( ++_hours >= 24 )
213
		_hours = 0;
214
}
215
216
217
void Time::inc_minutes()
218
{
219
	if( ++_minutes >= 60 )
220
		_minutes = 0;
221
}
222
223
224
void Time::reset_seconds()
225
{
226
	_seconds = 0;
227
}
228
229
230
void Time::inc_year()
231
{
232
	if( ++_year >= YEAR_MAX )
233
		_year = YEAR_MIN;
234
}
235
236
237
void Time::inc_month()
238
{
239
	if( ++_month > 12 )
240
		_month = 1;
241
}
242
243
244
void Time::inc_day()
245
{
246
	if( ++_day > days_in_month( _month, _year ) )
247
		_day = 1;
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
248
}
249
250