/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
29
#define YEAR_MIN 2010
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
33
static int _year;
34
35
// month
36
static int _month;
37
38
// day
39
static int _day;
40
41
// hours
42
static int _hours;
43
44
// minutes
45
static int _minutes;
46
47
// seconds
48
static int _seconds;
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
56 by edam
updated software to include drawing abstraction infrastructure
57
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
58
int Time::get_year()
59
{
60
	return _year;
61
}
62
63
64
int Time::get_month()
65
{
66
	return _month;
67
}
68
69
70
const char *Time::get_month_name()
71
{
72
	static const char *months[] = {
73
		"January",
74
		"February",
75
		"March",
76
		"April",
77
		"May",
78
		"June",
79
		"July",
80
		"August",
81
		"September",
82
		"October",
83
		"November",
84
		"December",
85
	};
86
87
	return months[ _month - 1 ];
88
}
89
90
91
int Time::get_day()
92
{
93
	return _day;
94
}
95
96
97
const char *Time::get_day_suffix()
98
{
99
	switch( _day )
100
	{
101
	case 1:
102
	case 21:
103
	case 31:
104
		return "st";
105
	case 2:
106
	case 22:
107
		return "nd";
108
	case 3:
109
	case 23:
110
		return "rd";
111
	default:
112
		return "th";
113
	}
114
}
115
116
56 by edam
updated software to include drawing abstraction infrastructure
117
int Time::get_hours()
118
{
119
	return _hours;
120
}
121
122
123
int Time::get_minutes()
124
{
125
	return _minutes;
126
}
127
128
129
int Time::get_seconds()
130
{
131
	return _seconds;
132
}
133
134
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
135
static int days_in_month( int month, int year )
136
{
137
	if( month == 2 )
138
		return !( year % 4 ) && ( ( year % 100 ) || !( year % 400 ) )? 29 : 28;
139
	else if( month == 9 || month == 6 || month == 4 || month == 11 )
140
		return 30;
141
	else
142
		return 31;
143
}
144
145
146
static void load_time()
147
{
148
	// get the time from the real-time clock
149
	int rtc_data[ 7 ];
150
	RTC.get( rtc_data, true );
151
	_year = rtc_data[ DS1307_YR ];
152
	_month = rtc_data[ DS1307_MTH ];
153
	_day = rtc_data[ DS1307_DAY ];
154
	_hours = rtc_data[ DS1307_HR ];
155
	_minutes = rtc_data[ DS1307_MIN ];
156
	_seconds = rtc_data[ DS1307_SEC ];
157
158
	// make sure some numbers are in range
159
	if( _year < YEAR_MIN || _year > YEAR_MAX ) _year = 2010;
160
	if( _month < 1 || _month > 12 ) _month = 1;
161
	if( _day < 1 || _day > days_in_month( _year, _month ) ) _day = 1;
162
}
163
164
56 by edam
updated software to include drawing abstraction infrastructure
165
void Time::update()
166
{
68 by Tim Marston
added frame reset code and inited minor mode flavours on mode activation
167
	// how many milliseconds have elapsed since we last checked?
56 by edam
updated software to include drawing abstraction infrastructure
168
	unsigned long millis = ::millis();
169
	unsigned long delta = millis - _last_millis + _carry;
170
171
	// update the previous time and carried-over milliseconds
172
	_last_millis = millis;
173
	_carry = delta % 1000;
174
175
	// add the seconds that have passed to the time
176
	_seconds += delta / 1000;
177
	while( _seconds >= 60 ) {
178
		_seconds -= 60;
179
		_minutes++;
180
		if( _minutes >= 60 ) {
181
			_minutes -= 60;
182
			_hours++;
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
183
			if( _hours >= 24 ) {
56 by edam
updated software to include drawing abstraction infrastructure
184
				_hours -= 24;
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
185
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
186
				// We *could* manually work out the day here... but we might as
187
				// well ask the RTC hardware. We can't do this *all* the time
188
				// though, because it isn't fast enough and will actually cause
189
				// a minor display glitch.
190
				load_time();
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
191
			}
56 by edam
updated software to include drawing abstraction infrastructure
192
		}
193
	}
194
}
195
196
66 by Tim Marston
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!
197
void Time::init()
56 by edam
updated software to include drawing abstraction infrastructure
198
{
71 by Tim Marston
added time set mode, made text renderer's buffer auto reset/output
199
	load_time();
200
}
201
202
203
static void save_time()
204
{
205
	// set the time on the real-time clock
206
	RTC.stop();
207
	RTC.set( DS1307_YR, _year );
208
	RTC.set( DS1307_MTH, _month );
209
	RTC.set( DS1307_DAY, _day );
210
	RTC.set( DS1307_HR, _hours );
211
	RTC.set( DS1307_MIN, _minutes );
212
	RTC.set( DS1307_SEC, _seconds );
213
	RTC.start();
214
}
215
216
217
void Time::inc_hours()
218
{
219
	if( ++_hours >= 24 )
220
		_hours = 0;
221
	save_time();
222
}
223
224
225
void Time::inc_minutes()
226
{
227
	if( ++_minutes >= 60 )
228
		_minutes = 0;
229
	save_time();
230
}
231
232
233
void Time::reset_seconds()
234
{
235
	_seconds = 0;
236
	save_time();
237
}
238
239
240
void Time::inc_year()
241
{
242
	if( ++_year >= YEAR_MAX )
243
		_year = YEAR_MIN;
244
	save_time();
245
}
246
247
248
void Time::inc_month()
249
{
250
	if( ++_month > 12 )
251
		_month = 1;
252
}
253
254
255
void Time::inc_day()
256
{
257
	if( ++_day > days_in_month( _month, _year ) )
258
		_day = 1;
259
	save_time();
62 by edam
moved some stuf round, created a re-usable pool of message buffers, genericised "modes" for messages
260
}
261
262