Subversion Repositories idreammicro-avr

Rev

Rev 18 | Rev 39 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
18 jlesech 1
/**************************************************************************//**
2
 * \brief DS1307 RTC library
3
 * \author Copyright (C) 2009  Julien Le Sech - www.idreammicro.com
4
 * \version 1.0
5
 * \date 20090501
6
 *
7
 * This file is part of the iDreamMicro library.
8
 *
9
 * This library is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU Lesser General Public License as published by the Free
11
 * Software Foundation, either version 3 of the License, or (at your option) any
12
 * later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program. If not, see http://www.gnu.org/licenses/
21
 ******************************************************************************/
22
 
23
/**************************************************************************//**
24
 * \file ds1307.c
25
 ******************************************************************************/
26
 
27
/******************************************************************************
28
 * Header file inclusions.
29
 ******************************************************************************/
30
 
31
#include <ds1307/ds1307.h>
32
 
33
#include <twi/twi.h>
34
#include <useful/datetime.h>
35
 
36
#include <assert.h>
37
#include <stdlib.h>
38
 
39
/******************************************************************************
40
 * Private macros.
41
 ******************************************************************************/
42
 
43
#define DS1307__ADDRESS                                         0x68
44
#define DS1307__SLAVE_ADDRESS               (DS1307__ADDRESS << 1)
45
 
46
#define DS1307__REGISTER_ADDRESS__SECONDS       0x00
47
#define DS1307__REGISTER_ADDRESS__MINUTES       0x01
48
#define DS1307__REGISTER_ADDRESS__HOURS         0x02
49
#define DS1307__REGISTER_ADDRESS__DAY           0x03
50
#define DS1307__REGISTER_ADDRESS__DATE          0x04
51
#define DS1307__REGISTER_ADDRESS__MONTH         0x05
52
#define DS1307__REGISTER_ADDRESS__YEAR          0x06
53
#define DS1307__REGISTER_ADDRESS__CONTROL       0x07
54
 
55
/******************************************************************************
56
 * Private function prototypes.
57
 ******************************************************************************/
58
 
59
/**************************************************************************//**
60
 * \fn static void ds1307__set_start_address(void)
61
 *
62
 * \brief Set RTC address to 0.
63
 ******************************************************************************/
64
static
65
void
66
ds1307__set_start_address
67
(
68
    void
69
);
70
 
71
/******************************************************************************
72
 * Public function definitions.
73
 ******************************************************************************/
74
 
75
/**************************************************************************//**
76
 * \fn void ds1307__initialize(void)
77
 *
78
 * \brief Initialize RTC.
79
 ******************************************************************************/
80
void
81
ds1307__initialize
82
(
83
    void
84
){
36 jlesech 85
    // We don't initialize TWI here: we may have several devices on the bus.
18 jlesech 86
    // Initialize TWI.
36 jlesech 87
    //twi__initialize(DS1307__CLOCK_RATE);
18 jlesech 88
}
89
 
90
/**************************************************************************//**
91
 * \fn void ds1307__get_time(
92
 * date_time__time_t*   p_time,
93
 * ds1307__hour_mode_t* p_hour_mode)
94
 *
95
 * \brief Get RTC time.
96
 *
97
 * \param p_time a pointer to fill with RTC time
98
 * \param p_hour_mode a pointer to fill with RTC hour mode
99
 ******************************************************************************/
100
void
101
ds1307__get_time
102
(
103
    datetime__time_t*      p_time,
104
    ds1307__hour_mode_t*    p_hour_mode
105
){
106
    // Check the preconditions.
107
    assert(NULL != p_time);
108
    assert(NULL != p_hour_mode);
109
 
110
    twi__start();
111
    twi__send_slaw(DS1307__SLAVE_ADDRESS);
112
    twi__send_data(DS1307__REGISTER_ADDRESS__SECONDS);
113
    twi__stop();
114
 
115
    twi__start();
116
    twi__send_slar(DS1307__SLAVE_ADDRESS);
117
    uint8_t seconds = 0;
118
    twi__receive_data_ack(&seconds);
119
    uint8_t minutes = 0;
120
    twi__receive_data_ack(&minutes);
121
    uint8_t hours = 0;
122
    twi__receive_data_nack(&hours);
123
    p_time->seconds = (((seconds & 0x70) >> 4) * 10) + (seconds & 0x0F);
124
    p_time->minutes = (((minutes & 0x70) >> 4) * 10) + (minutes & 0x0F);
125
    *p_hour_mode = (ds1307__hour_mode_t)((hours & 0x40) >> 6);
126
    if (DS1307__HOUR_MODE__12_HOUR == *p_hour_mode)
127
    {
128
        p_time->meridiem = (datetime__meridiem_t)((hours & 0x20) >> 5);
129
        p_time->hours = (((hours & 0x10) >> 4) * 10) + (hours & 0x0F);
130
    }
131
    else
132
    {
133
        p_time->hours = (((hours & 0x30) >> 4) * 10) + (hours & 0x0F);
134
    }
135
    twi__stop();
136
}
137
 
138
/**************************************************************************//**
139
 * \fn void ds1307__set_time(
140
 * date_time__time_t* p_time,
141
 * ds1307__hour_mode_t hour_mode)
142
 *
143
 * \brief Set RTC time.
144
 *
145
 * \param p_time time to set. p_time->meridiem isn't used in 12-hour mode.
146
 * \param hour_mode hour mode
147
 ******************************************************************************/
148
void
149
ds1307__set_time
150
(
151
    datetime__time_t*  p_time,
152
    ds1307__hour_mode_t hour_mode
153
){
154
    // Check the preconditions.
155
    assert(NULL != p_time);
156
 
157
    twi__start();
158
    twi__send_slaw(DS1307__SLAVE_ADDRESS);
159
    twi__send_data(DS1307__REGISTER_ADDRESS__SECONDS);
160
 
161
    uint8_t seconds = ((p_time->seconds / 10) << 4) + (p_time->seconds % 10);
162
    uint8_t minutes = ((p_time->minutes / 10) << 4) + (p_time->minutes % 10);
163
    uint8_t hours = 0;
164
    if (DS1307__HOUR_MODE__12_HOUR == hour_mode)
165
    {
166
        hours = (hour_mode << 6) + (p_time->meridiem << 5)
167
            + ((p_time->hours / 10) << 4) + (p_time->hours % 10);
168
    }
169
    else
170
    {
171
        hours = (hour_mode << 6) + ((p_time->hours / 10) << 4)
172
            + (p_time->hours % 10);
173
    }
174
 
175
    twi__send_data(seconds);
176
    twi__send_data(minutes);
177
    twi__send_data(hours);
178
 
179
    twi__stop();
180
}
181
 
182
/**************************************************************************//**
183
 * \fn void ds1307__get_date(date_time__date_t* p_date)
184
 *
185
 * \brief Get RTC date.
186
 *
187
 * \param p_date a pointer to fill with RTC date
188
 ******************************************************************************/
189
void
190
ds1307__get_date
191
(
192
    datetime__date_t* p_date
193
){
194
    // Check the preconditions.
195
    assert(NULL != p_date);
196
 
197
    twi__start();
198
    twi__send_slaw(DS1307__SLAVE_ADDRESS);
199
    twi__send_data(DS1307__REGISTER_ADDRESS__DAY);
200
    twi__stop();
201
 
202
    twi__start();
203
    twi__send_slar(DS1307__SLAVE_ADDRESS);
204
 
205
    uint8_t day = 0;
206
    twi__receive_data_ack(&day);
207
    uint8_t date = 0;
208
    twi__receive_data_ack(&date);
209
    uint8_t month = 0;
210
    twi__receive_data_ack(&month);
211
    uint8_t year = 0;
212
    twi__receive_data_nack(&year);
213
 
214
    p_date->day = day;
215
    p_date->date = (((date & 0x30) >> 4) * 10) + (date & 0x0F);
216
    p_date->month = (((month & 0x10) >> 4) * 10) + (month & 0x0F);
217
    p_date->year = (((year & 0xF0) >> 4) * 10) + (year & 0x0F);
218
 
219
    twi__stop();
220
}
221
 
222
/**************************************************************************//**
223
 * \fn void ds1307__set_date(date_time__date_t* p_date)
224
 *
225
 * \brief Set RTC date.
226
 *
227
 * \param p_date date to set
228
 ******************************************************************************/
229
void
230
ds1307__set_date
231
(
232
    datetime__date_t* p_date
233
){
234
    // Check the preconditions.
235
    assert(NULL != p_date);
236
 
237
    twi__start();
238
    twi__send_slaw(DS1307__SLAVE_ADDRESS);
239
    twi__send_data(DS1307__REGISTER_ADDRESS__DAY);
240
 
241
    uint8_t date = ((p_date->date / 10) << 4) + (p_date->date % 10);
242
    uint8_t month = ((p_date->month / 10) << 4) + (p_date->month % 10);
243
    uint8_t year = ((p_date->year / 10) << 4) + (p_date->year % 10);
244
 
245
    twi__send_data(p_date->day);
246
    twi__send_data(date);
247
    twi__send_data(month);
248
    twi__send_data(year);
249
 
250
    twi__stop();
251
}
252
 
253
/******************************************************************************
254
 * Private function definitions.
255
 ******************************************************************************/
256
 
257
/**************************************************************************//**
258
 * \fn static void ds1307__set_start_address(void)
259
 *
260
 * \brief Set RTC address to 0.
261
 ******************************************************************************/
262
static
263
void
264
ds1307__set_start_address
265
(
266
    void
267
){
268
    twi__start();
269
    twi__send_slaw(DS1307__SLAVE_ADDRESS);
270
    twi__send_data(0);
271
    twi__stop();
272
}