Subversion Repositories idreammicro-arduino

Rev

Rev 21 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
21 jlesech 1
/**************************************************************************//**
2
 * \brief Arduino clock.
3
 * \author Copyright (C) 2012  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20120428
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program. If not, see http://www.gnu.org/licenses.
19
 ******************************************************************************/
20
 
21
/**************************************************************************//**
22
 * \file clock.ino
23
 ******************************************************************************/
24
 
25
/******************************************************************************
26
 * Header file inclusions.
27
 ******************************************************************************/
28
 
29
#include "Keyboard.h"
30
 
31
#include <Deuligne.h>
32
#include <RTClib.h>
33
 
34
#include <Arduino.h>
35
#include <Wire.h>
36
 
37
#include <stdio.h>
38
 
39
/******************************************************************************
40
 * Private macro definitions.
41
 ******************************************************************************/
42
 
43
#define CLOCK__DAY_MIN     1
44
#define CLOCK__DAY_MAX     31
45
#define CLOCK__MONTH_MIN   1
46
#define CLOCK__MONTH_MAX   12
47
#define CLOCK__YEAR_MIN    2000
48
#define CLOCK__YEAR_MAX    2099
49
#define CLOCK__HOUR_MIN    0
50
#define CLOCK__HOUR_MAX    23
51
#define CLOCK__MINUTE_MIN  0
52
#define CLOCK__MINUTE_MAX  59
53
#define CLOCK__SECOND_MIN  0
54
#define CLOCK__SECOND_MAX  59
55
 
56
/******************************************************************************
57
 * Private type definitions.
58
 ******************************************************************************/
59
 
60
/**************************************************************************//**
61
 * \enum clock__members
62
 * \brief
63
 *
64
 * \type clock__member_t
65
 * \brief
66
 ******************************************************************************/
67
typedef enum clock__members
68
{
69
    clock__MemberDay,
70
    clock__MemberMonth,
71
    clock__MemberYear,
72
    clock__MemberHour,
73
    clock__MemberMinute,
74
    clock__MemberSecond
75
} clock__member_t;
76
 
77
/******************************************************************************
78
 * Private function prototypes.
79
 ******************************************************************************/
80
 
81
/**************************************************************************//**
82
 * \fn static void clock__handleKey(Keyboard::Key_t key)
83
 *
84
 * \brief Handle pressed key.
85
 *
86
 * \param   key Pressed key.
87
 ******************************************************************************/
88
static
89
void
90
clock__handleKey
91
(
92
    Keyboard::Key_t key
93
);
94
 
95
/**************************************************************************//**
96
 * \fn static void clock__setCursor()
97
 *
98
 * \brief Set cursor position.
99
 ******************************************************************************/
100
static
101
void
102
clock__setCursor();
103
 
104
/**************************************************************************//**
105
 * \fn static clock__incrementMember()
106
 *
107
 * \brief Increment current member: day, month, year, hour, minute or second.
108
 ******************************************************************************/
109
static
110
void
111
clock__incrementMember();
112
 
113
/**************************************************************************//**
114
 * \fn static void clock__decrementMember()
115
 *
116
 * \brief Decrement current member: day, month, year, hour, minute or second.
117
 ******************************************************************************/
118
static
119
void
120
clock__decrementMember();
121
 
122
/**************************************************************************//**
123
 * \fn static void clock__printDatetime()
124
 *
125
 * \brief Print current datetime.
126
 ******************************************************************************/
127
static
128
void
129
clock__printDatetime();
130
 
131
/******************************************************************************
132
 * Private variable declarations.
133
 ******************************************************************************/
134
 
135
static Deuligne clock__lcd;
136
static RTC_DS1307 clock__rtc;
137
 
138
static DateTime clock__currentTime;
139
 
140
static bool clock__adjustMode = false;
141
static clock__member_t clock__currentMember = clock__MemberDay;
142
 
143
/******************************************************************************
144
 * Public function definitions.
145
 ******************************************************************************/
146
 
147
/**************************************************************************//**
148
 * \fn void setup()
149
 *
150
 * \brief System initialization.
151
 ******************************************************************************/
152
void setup()
153
{
154
    // Initialize TWI bus.
155
    Wire.begin();
156
 
157
    // Initialize RTC.
158
    clock__rtc.begin();
159
 
160
    // Initialize LCD.
161
    clock__lcd.init();
162
    clock__lcd.clear();
163
    clock__lcd.backLight(true);
164
 
165
    // Get current time and print it.
166
    clock__currentTime = clock__rtc.now();
167
    clock__printDatetime();
168
}
169
 
170
/**************************************************************************//**
171
 * \fn void loop()
172
 *
173
 * \brief Infinite loop.
174
 ******************************************************************************/
175
void loop()
176
{
177
    // Get pressed key and process it.
178
    Keyboard::Key_t key = (Keyboard::Key_t)(clock__lcd.get_key());
179
    if (key > Keyboard::KeyNone)
180
    {
181
        clock__handleKey(key);
182
    }
183
 
184
    // If we aren't in adjust mode, get current time and print it.
185
    if (!clock__adjustMode)
186
    {
187
        clock__currentTime = clock__rtc.now();
188
        clock__printDatetime();
189
    }
190
 
191
    delay(200);
192
}
193
 
194
/******************************************************************************
195
 * Private function definitions.
196
 ******************************************************************************/
197
 
198
/**************************************************************************//**
199
 * \fn static void clock__handleKey(Keyboard::Key_t key)
200
 *
201
 * \brief Handle pressed key.
202
 *
203
 * \param   key Pressed key.
204
 ******************************************************************************/
205
static
206
void
207
clock__handleKey
208
(
209
    Keyboard::Key_t key
210
){
211
    switch (key)
212
    {
213
        case Keyboard::KeyRight:
214
        {
215
            if (clock__adjustMode)
216
            {
217
                if (clock__currentMember < clock__MemberSecond)
218
                {
219
                    byte tmpMember = (byte)clock__currentMember;
220
                    tmpMember++;
221
                    clock__currentMember = (clock__member_t)tmpMember;
222
                }
223
                else
224
                {
225
                    clock__currentMember = clock__MemberDay;
226
                }
227
                clock__setCursor();
228
            }
229
        }
230
        break;
231
 
232
        case Keyboard::KeyUp:
233
        {
234
            if (clock__adjustMode)
235
            {
236
                clock__incrementMember();
237
                clock__setCursor();
238
            }
239
        }
240
        break;
241
 
242
        case Keyboard::KeyDown:
243
        {
244
            if (clock__adjustMode)
245
            {
246
                clock__decrementMember();
247
                clock__setCursor();
248
            }
249
        }
250
        break;
251
 
252
        case Keyboard::KeyLeft:
253
        {
254
            if (clock__adjustMode)
255
            {
256
                if (clock__currentMember > clock__MemberDay)
257
                {
258
                    byte tmpMember = (byte)clock__currentMember;
259
                    tmpMember--;
260
                    clock__currentMember = (clock__member_t)tmpMember;
261
                }
262
                else
263
                {
264
                    clock__currentMember = clock__MemberSecond;
265
                }
266
                clock__setCursor();
267
            }
268
        }
269
        break;
270
 
271
        case Keyboard::KeySelect:
272
        {
273
            if (clock__adjustMode)
274
            {
275
                // If we are in adjust mode, update RTC time.
276
                clock__rtc.adjust(clock__currentTime);
277
                clock__lcd.noBlink();
278
                clock__lcd.noCursor();
279
                clock__currentMember = clock__MemberDay;
280
                clock__adjustMode = false;
281
            }
282
            else
283
            {
284
                // Enter adjust mode.
285
                clock__adjustMode = true;
286
                clock__lcd.setCursor(1, 0);
287
                clock__lcd.blink();
288
                clock__lcd.cursor();
289
            }
290
        }
291
        break;
292
 
293
        case Keyboard::KeyNone:
294
        case Keyboard::KeyInvalid:
295
        default:
296
        break;
297
    }
298
}
299
 
300
/**************************************************************************//**
301
 * \fn static void clock__setCursor()
302
 *
303
 * \brief Set cursor position.
304
 ******************************************************************************/
305
static
306
void
307
clock__setCursor()
308
{
309
    switch (clock__currentMember)
310
    {
311
        case clock__MemberDay:
312
            clock__lcd.setCursor(1, 0);
313
        break;
314
 
315
        case clock__MemberMonth:
316
            clock__lcd.setCursor(4, 0);
317
        break;
318
 
319
        case clock__MemberYear:
320
            clock__lcd.setCursor(9, 0);
321
        break;
322
 
323
        case clock__MemberHour:
324
            clock__lcd.setCursor(1, 1);
325
        break;
326
 
327
        case clock__MemberMinute:
328
            clock__lcd.setCursor(4, 1);
329
        break;
330
 
331
        case clock__MemberSecond:
332
            clock__lcd.setCursor(7, 1);
333
        break;
334
 
335
        default:
336
        break;
337
    }
338
}
339
 
340
/**************************************************************************//**
341
 * \fn static void clock__incrementMember()
342
 *
343
 * \brief Increment current member: day, month, year, hour, minute or second.
344
 ******************************************************************************/
345
static
346
void
347
clock__incrementMember()
348
{
349
    switch (clock__currentMember)
350
    {
351
        case clock__MemberDay:
352
        {
353
            byte day = clock__currentTime.day();
354
            day = (day + 1 <= CLOCK__DAY_MAX) ? (day + 1) : CLOCK__DAY_MIN;
24 jlesech 355
            clock__currentTime.setDay(day);
21 jlesech 356
        }
357
        break;
358
 
359
        case clock__MemberMonth:
360
        {
361
            byte month = clock__currentTime.month();
362
            month = (month + 1 <= CLOCK__MONTH_MAX) ? (month + 1) : CLOCK__MONTH_MIN;
24 jlesech 363
            clock__currentTime.setMonth(month);
21 jlesech 364
        }
365
        break;
366
 
367
        case clock__MemberYear:
368
        {
369
            word year = clock__currentTime.year();
370
            year = (year + 1 <= CLOCK__YEAR_MAX) ? (year + 1) : CLOCK__YEAR_MIN;
24 jlesech 371
            clock__currentTime.setYear(year);
21 jlesech 372
        }
373
        break;
374
 
375
        case clock__MemberHour:
376
        {
377
            byte hour = clock__currentTime.hour();
378
            hour = (hour + 1 <= CLOCK__HOUR_MAX) ? (hour + 1) : CLOCK__HOUR_MIN;
24 jlesech 379
            clock__currentTime.setHour(hour);
21 jlesech 380
        }
381
        break;
382
 
383
        case clock__MemberMinute:
384
        {
385
            byte minute = clock__currentTime.minute();
386
            minute = (minute + 1 <= CLOCK__MINUTE_MAX) ? (minute + 1) : CLOCK__MINUTE_MIN;
24 jlesech 387
            clock__currentTime.setMinute(minute);
21 jlesech 388
        }
389
        break;
390
 
391
        case clock__MemberSecond:
392
        {
393
            byte second = clock__currentTime.second();
394
            second = (second + 1 <= CLOCK__SECOND_MAX) ? (second + 1) : CLOCK__SECOND_MIN;
24 jlesech 395
            clock__currentTime.setSecond(second);
21 jlesech 396
        }
397
        break;
398
 
399
        default:
400
        break;
401
    }
402
    clock__printDatetime();
403
}
404
 
405
/**************************************************************************//**
406
 * \fn static void clock__decrementMember()
407
 *
408
 * \brief Decrement current member: day, month, year, hour, minute or second.
409
 ******************************************************************************/
410
static
411
void
412
clock__decrementMember()
413
{
414
    switch (clock__currentMember)
415
    {
416
        case clock__MemberDay:
417
        {
418
            byte day = clock__currentTime.day();
419
            day = (day - 1 >= CLOCK__DAY_MIN) ? (day - 1) : CLOCK__DAY_MAX;
24 jlesech 420
            clock__currentTime.setDay(day);
21 jlesech 421
        }
422
        break;
423
 
424
        case clock__MemberMonth:
425
        {
426
            byte month = clock__currentTime.month();
427
            month = (month - 1 >= CLOCK__MONTH_MIN) ? (month - 1) : CLOCK__MONTH_MAX;
24 jlesech 428
            clock__currentTime.setMonth(month);
21 jlesech 429
        }
430
        break;
431
 
432
        case clock__MemberYear:
433
        {
434
            word year = clock__currentTime.year();
435
            year = (year - 1 >= CLOCK__YEAR_MIN) ? (year - 1) : CLOCK__YEAR_MAX;
24 jlesech 436
            clock__currentTime.setYear(year);
21 jlesech 437
        }
438
        break;
439
 
440
        case clock__MemberHour:
441
        {
442
            byte hour = clock__currentTime.hour();
443
            hour = (hour - 1 >= CLOCK__HOUR_MIN) ? (hour - 1) : CLOCK__HOUR_MIN;
24 jlesech 444
            clock__currentTime.setHour(hour);
21 jlesech 445
        }
446
        break;
447
 
448
        case clock__MemberMinute:
449
        {
450
            byte minute = clock__currentTime.minute();
451
            minute = (minute - 1 >= CLOCK__MINUTE_MIN) ? (minute - 1) : CLOCK__MINUTE_MAX;
24 jlesech 452
            clock__currentTime.setMinute(minute);
21 jlesech 453
        }
454
        break;
455
 
456
        case clock__MemberSecond:
457
        {
458
            byte second = clock__currentTime.second();
459
            second = (second - 1 >= CLOCK__SECOND_MIN) ? (second - 1) : CLOCK__SECOND_MAX;
24 jlesech 460
            clock__currentTime.setSecond(second);
21 jlesech 461
        }
462
        break;
463
 
464
        default:
465
        break;
466
    }
467
    clock__printDatetime();
468
}
469
 
470
/**************************************************************************//**
471
 * \fn static void clock__printDatetime()
472
 *
473
 * \brief Print current datetime.
474
 ******************************************************************************/
475
static
476
void
477
clock__printDatetime()
478
{
479
    // Build date string.
480
    char date[] = "01/01/2000";
481
    snprintf
482
    (
483
        date,
484
        strlen(date) + 1,
485
        "%02d/%02d/%04d",
486
        clock__currentTime.day(),
487
        clock__currentTime.month(),
488
        clock__currentTime.year()
489
    );
490
 
491
    // Build time string.
492
    char time[] = "00:00:00";
493
    snprintf
494
    (
495
        time,
496
        strlen(time) + 1,
497
        "%02d:%02d:%02d",
498
        clock__currentTime.hour(),
499
        clock__currentTime.minute(),
500
        clock__currentTime.second()
501
    );
502
 
503
    // Print date.
504
    clock__lcd.setCursor(0, 0);
505
    clock__lcd.print(date);
506
 
507
    // Print time.
508
    clock__lcd.setCursor(0, 1);
509
    clock__lcd.print(time);
510
}