Subversion Repositories idreammicro-arduino

Rev

Go to most recent revision | Details | 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;
355
            DateTime tempTime
356
            (
357
                clock__currentTime.year(),
358
                clock__currentTime.month(),
359
                day,
360
                clock__currentTime.hour(),
361
                clock__currentTime.minute(),
362
                clock__currentTime.second()
363
            );
364
            clock__currentTime = tempTime;
365
        }
366
        break;
367
 
368
        case clock__MemberMonth:
369
        {
370
            byte month = clock__currentTime.month();
371
            month = (month + 1 <= CLOCK__MONTH_MAX) ? (month + 1) : CLOCK__MONTH_MIN;
372
            DateTime tempTime
373
            (
374
                clock__currentTime.year(),
375
                month,
376
                clock__currentTime.day(),
377
                clock__currentTime.hour(),
378
                clock__currentTime.minute(),
379
                clock__currentTime.second()
380
            );
381
            clock__currentTime = tempTime;
382
        }
383
        break;
384
 
385
        case clock__MemberYear:
386
        {
387
            word year = clock__currentTime.year();
388
            year = (year + 1 <= CLOCK__YEAR_MAX) ? (year + 1) : CLOCK__YEAR_MIN;
389
            DateTime tempTime
390
            (
391
                year,
392
                clock__currentTime.month(),
393
                clock__currentTime.day(),
394
                clock__currentTime.hour(),
395
                clock__currentTime.minute(),
396
                clock__currentTime.second()
397
            );
398
            clock__currentTime = tempTime;
399
        }
400
        break;
401
 
402
        case clock__MemberHour:
403
        {
404
            byte hour = clock__currentTime.hour();
405
            hour = (hour + 1 <= CLOCK__HOUR_MAX) ? (hour + 1) : CLOCK__HOUR_MIN;
406
            DateTime tempTime
407
            (
408
                clock__currentTime.year(),
409
                clock__currentTime.month(),
410
                clock__currentTime.day(),
411
                hour,
412
                clock__currentTime.minute(),
413
                clock__currentTime.second()
414
            );
415
            clock__currentTime = tempTime;
416
        }
417
        break;
418
 
419
        case clock__MemberMinute:
420
        {
421
            byte minute = clock__currentTime.minute();
422
            minute = (minute + 1 <= CLOCK__MINUTE_MAX) ? (minute + 1) : CLOCK__MINUTE_MIN;
423
            DateTime tempTime
424
            (
425
                clock__currentTime.year(),
426
                clock__currentTime.month(),
427
                clock__currentTime.day(),
428
                clock__currentTime.hour(),
429
                minute,
430
                clock__currentTime.second()
431
            );
432
            clock__currentTime = tempTime;
433
        }
434
        break;
435
 
436
        case clock__MemberSecond:
437
        {
438
            byte second = clock__currentTime.second();
439
            second = (second + 1 <= CLOCK__SECOND_MAX) ? (second + 1) : CLOCK__SECOND_MIN;
440
            DateTime tempTime
441
            (
442
                clock__currentTime.year(),
443
                clock__currentTime.month(),
444
                clock__currentTime.day(),
445
                clock__currentTime.hour(),
446
                clock__currentTime.minute(),
447
                second
448
            );
449
            clock__currentTime = tempTime;
450
        }
451
        break;
452
 
453
        default:
454
        break;
455
    }
456
    clock__printDatetime();
457
}
458
 
459
/**************************************************************************//**
460
 * \fn static void clock__decrementMember()
461
 *
462
 * \brief Decrement current member: day, month, year, hour, minute or second.
463
 ******************************************************************************/
464
static
465
void
466
clock__decrementMember()
467
{
468
    switch (clock__currentMember)
469
    {
470
        case clock__MemberDay:
471
        {
472
            byte day = clock__currentTime.day();
473
            day = (day - 1 >= CLOCK__DAY_MIN) ? (day - 1) : CLOCK__DAY_MAX;
474
            DateTime tempTime
475
            (
476
                clock__currentTime.year(),
477
                clock__currentTime.month(),
478
                day,
479
                clock__currentTime.hour(),
480
                clock__currentTime.minute(),
481
                clock__currentTime.second()
482
            );
483
            clock__currentTime = tempTime;
484
        }
485
        break;
486
 
487
        case clock__MemberMonth:
488
        {
489
            byte month = clock__currentTime.month();
490
            month = (month - 1 >= CLOCK__MONTH_MIN) ? (month - 1) : CLOCK__MONTH_MAX;
491
            DateTime tempTime
492
            (
493
                clock__currentTime.year(),
494
                month,
495
                clock__currentTime.day(),
496
                clock__currentTime.hour(),
497
                clock__currentTime.minute(),
498
                clock__currentTime.second()
499
            );
500
            clock__currentTime = tempTime;
501
        }
502
        break;
503
 
504
        case clock__MemberYear:
505
        {
506
            word year = clock__currentTime.year();
507
            year = (year - 1 >= CLOCK__YEAR_MIN) ? (year - 1) : CLOCK__YEAR_MAX;
508
            DateTime tempTime
509
            (
510
                year,
511
                clock__currentTime.month(),
512
                clock__currentTime.day(),
513
                clock__currentTime.hour(),
514
                clock__currentTime.minute(),
515
                clock__currentTime.second()
516
            );
517
            clock__currentTime = tempTime;
518
        }
519
        break;
520
 
521
        case clock__MemberHour:
522
        {
523
            byte hour = clock__currentTime.hour();
524
            hour = (hour - 1 >= CLOCK__HOUR_MIN) ? (hour - 1) : CLOCK__HOUR_MIN;
525
            DateTime tempTime
526
            (
527
                clock__currentTime.year(),
528
                clock__currentTime.month(),
529
                clock__currentTime.day(),
530
                hour,
531
                clock__currentTime.minute(),
532
                clock__currentTime.second()
533
            );
534
            clock__currentTime = tempTime;
535
        }
536
        break;
537
 
538
        case clock__MemberMinute:
539
        {
540
            byte minute = clock__currentTime.minute();
541
            minute = (minute - 1 >= CLOCK__MINUTE_MIN) ? (minute - 1) : CLOCK__MINUTE_MAX;
542
            DateTime tempTime
543
            (
544
                clock__currentTime.year(),
545
                clock__currentTime.month(),
546
                clock__currentTime.day(),
547
                clock__currentTime.hour(),
548
                minute,
549
                clock__currentTime.second()
550
            );
551
            clock__currentTime = tempTime;
552
        }
553
        break;
554
 
555
        case clock__MemberSecond:
556
        {
557
            byte second = clock__currentTime.second();
558
            second = (second - 1 >= CLOCK__SECOND_MIN) ? (second - 1) : CLOCK__SECOND_MAX;
559
            DateTime tempTime
560
            (
561
                clock__currentTime.year(),
562
                clock__currentTime.month(),
563
                clock__currentTime.day(),
564
                clock__currentTime.hour(),
565
                clock__currentTime.minute(),
566
                second
567
            );
568
            clock__currentTime = tempTime;
569
        }
570
        break;
571
 
572
        default:
573
        break;
574
    }
575
    clock__printDatetime();
576
}
577
 
578
/**************************************************************************//**
579
 * \fn static void clock__printDatetime()
580
 *
581
 * \brief Print current datetime.
582
 ******************************************************************************/
583
static
584
void
585
clock__printDatetime()
586
{
587
    // Build date string.
588
    char date[] = "01/01/2000";
589
    snprintf
590
    (
591
        date,
592
        strlen(date) + 1,
593
        "%02d/%02d/%04d",
594
        clock__currentTime.day(),
595
        clock__currentTime.month(),
596
        clock__currentTime.year()
597
    );
598
 
599
    // Build time string.
600
    char time[] = "00:00:00";
601
    snprintf
602
    (
603
        time,
604
        strlen(time) + 1,
605
        "%02d:%02d:%02d",
606
        clock__currentTime.hour(),
607
        clock__currentTime.minute(),
608
        clock__currentTime.second()
609
    );
610
 
611
    // Print date.
612
    clock__lcd.setCursor(0, 0);
613
    clock__lcd.print(date);
614
 
615
    // Print time.
616
    clock__lcd.setCursor(0, 1);
617
    clock__lcd.print(time);
618
}