Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 226 lines (189 sloc) 6.525 kb
da52711 Added files and written a bit of README
github@signout.dk authored
1 // Code by JeeLabs http://news.jeelabs.org/code/
2 // Released to the public domain! Enjoy!
3
4 #include <Wire.h>
5 #include <avr/pgmspace.h>
6 #include "DS1340lib.h"
7 #include <WProgram.h>
8
9 #define DS1340_ADDRESS 0x68
10 #define SECONDS_PER_DAY 86400L
11
12 #define SECONDS_FROM_1970_TO_2000 946684800
13
14 ////////////////////////////////////////////////////////////////////////////////
15 // utility code, some of this could be exposed in the DateTime API if needed
16
17 static uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
18
19 // number of days since 2000/01/01, valid for 2001..2099
20 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
21 if (y >= 2000)
22 y -= 2000;
23 uint16_t days = d;
24 for (uint8_t i = 1; i < m; ++i)
25 days += pgm_read_byte(daysInMonth + i - 1);
26 if (m > 2 && y % 4 == 0)
27 ++days;
28 return days + 365 * y + (y + 3) / 4 - 1;
29 }
30
31 static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
32 return ((days * 24L + h) * 60 + m) * 60 + s;
33 }
34
35 ////////////////////////////////////////////////////////////////////////////////
36 // DateTime implementation - ignores time zones and DST changes
37 // NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
38
39 DateTime::DateTime (uint32_t t) {
40 t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
41
42 ss = t % 60;
43 t /= 60;
44 mm = t % 60;
45 t /= 60;
46 hh = t % 24;
47 uint16_t days = t / 24;
48 uint8_t leap;
49 for (yOff = 0; ; ++yOff) {
50 leap = yOff % 4 == 0;
51 if (days < 365 + leap)
52 break;
53 days -= 365 + leap;
54 }
55 for (m = 1; ; ++m) {
56 uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
57 if (leap && m == 2)
58 ++daysPerMonth;
59 if (days < daysPerMonth)
60 break;
61 days -= daysPerMonth;
62 }
63 d = days + 1;
64 }
65
66 DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
67 if (year >= 2000)
68 year -= 2000;
69 yOff = year;
70 m = month;
71 d = day;
72 hh = hour;
73 mm = min;
74 ss = sec;
75 }
76
77 static uint8_t conv2d(const char* p) {
78 uint8_t v = 0;
79 if ('0' <= *p && *p <= '9')
80 v = *p - '0';
81 return 10 * v + *++p - '0';
82 }
83
84 // A convenient constructor for using "the compiler's time":
85 // DateTime now (__DATE__, __TIME__);
86 // NOTE: using PSTR would further reduce the RAM footprint
87 DateTime::DateTime (const char* date, const char* time) {
88 // sample input: date = "Dec 26 2009", time = "12:34:56"
89 yOff = conv2d(date + 9);
90 // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
91 switch (date[0]) {
92 case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
93 case 'F': m = 2; break;
94 case 'A': m = date[2] == 'r' ? 4 : 8; break;
95 case 'M': m = date[2] == 'r' ? 3 : 5; break;
96 case 'S': m = 9; break;
97 case 'O': m = 10; break;
98 case 'N': m = 11; break;
99 case 'D': m = 12; break;
100 }
101 d = conv2d(date + 4);
102 hh = conv2d(time);
103 mm = conv2d(time + 3);
104 ss = conv2d(time + 6);
105 }
106
107 uint8_t DateTime::dayOfWeek() const {
108 uint16_t day = date2days(yOff, m, d);
109 return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
110 }
111
112 uint32_t DateTime::unixtime(void) const {
113 uint32_t t;
114 uint16_t days = date2days(yOff, m, d);
115 t = time2long(days, hh, mm, ss);
116 t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
117
118 return t;
119 }
120
121 ////////////////////////////////////////////////////////////////////////////////
122 // RTC_DS1340 implementation
123
124 static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
125 static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
126
127 uint8_t RTC_DS1340::begin(void) {
128 return 1;
129 }
130
131 uint8_t RTC_DS1340::isrunning(void) {
132 Wire.beginTransmission(DS1340_ADDRESS);
133 Wire.send(0);
134 Wire.endTransmission();
135
136 Wire.requestFrom(DS1340_ADDRESS, 1);
137 uint8_t ss = Wire.receive();
138 return !(ss>>7);
139 }
140
141 void RTC_DS1340::adjust(const DateTime& dt) {
142 Wire.beginTransmission(DS1340_ADDRESS);
143 Wire.send(0);
144 Wire.send(bin2bcd(dt.second()));
145 Wire.send(bin2bcd(dt.minute()));
146 Wire.send(bin2bcd(dt.hour()));
147 Wire.send(bin2bcd(0));
148 Wire.send(bin2bcd(dt.day()));
149 Wire.send(bin2bcd(dt.month()));
150 Wire.send(bin2bcd(dt.year() - 2000));
151 Wire.send(0);
152 Wire.endTransmission();
153 }
154
155 DateTime RTC_DS1340::enabletricklecharger() {
156 Wire.beginTransmission(DS1340_ADDRESS);
157 Wire.send(8);
ebf6fa3 Added comment about trickle charge
github@signout.dk authored
158 Wire.send(0xA6); // No diode, 2k resistor (Don't use 250 ohm on arduino. It will burn the resistor with VCC above 3.63V)
da52711 Added files and written a bit of README
github@signout.dk authored
159 Wire.endTransmission();
160 }
161
162 DateTime RTC_DS1340::disabletricklecharger() {
163 Wire.beginTransmission(DS1340_ADDRESS);
164 Wire.send(8);
165 Wire.send(0x00); // No charge at all
166 Wire.endTransmission();
167 }
168
169 DateTime RTC_DS1340::enableFTout() {
170 Wire.beginTransmission(DS1340_ADDRESS);
171 Wire.send(7);
172 Wire.endTransmission();
173
174 Wire.requestFrom(DS1340_ADDRESS, 1);
175 uint8_t setreg = Wire.receive() | 0xC0; // Read from address 7 and set OUT and FT high
176 Wire.beginTransmission(DS1340_ADDRESS);
177 Wire.send(7);
178 Wire.send(setreg); // Put the values back where they came from
179 Wire.endTransmission();
180 }
181
182 DateTime RTC_DS1340::disableFTout() {
183 Wire.beginTransmission(DS1340_ADDRESS);
184 Wire.send(7);
185 Wire.endTransmission();
186
187 Wire.requestFrom(DS1340_ADDRESS, 1);
188 uint8_t setreg = Wire.receive() & 0xBF; // Read from address 7 and set FT low
189 Wire.beginTransmission(DS1340_ADDRESS);
190 Wire.send(7);
191 Wire.send(setreg); // Write the values back
192 Wire.endTransmission();
193 }
194
195 DateTime RTC_DS1340::now() {
196 Wire.beginTransmission(DS1340_ADDRESS);
197 Wire.send(0);
198 Wire.endTransmission();
199
200 Wire.requestFrom(DS1340_ADDRESS, 7);
201 uint8_t ss = bcd2bin(Wire.receive() & 0x7F);
202 uint8_t mm = bcd2bin(Wire.receive());
203 uint8_t hh = bcd2bin(Wire.receive());
204 Wire.receive();
205 uint8_t d = bcd2bin(Wire.receive());
206 uint8_t m = bcd2bin(Wire.receive());
207 uint16_t y = bcd2bin(Wire.receive()) + 2000;
208
209 return DateTime (y, m, d, hh, mm, ss);
210 }
211
212 ////////////////////////////////////////////////////////////////////////////////
213 // RTC_Millis implementation
214
215 long RTC_Millis::offset = 0;
216
217 void RTC_Millis::adjust(const DateTime& dt) {
218 offset = dt.unixtime() - millis() / 1000;
219 }
220
221 DateTime RTC_Millis::now() {
222 return (uint32_t)(offset + millis() / 1000);
223 }
224
225 ////////////////////////////////////////////////////////////////////////////////
Something went wrong with that request. Please try again.