Updated to latest version
[hackover2013-badge-firmware.git] / drivers / rtc / isl12022m / isl12022m.c
1 /**************************************************************************/
2 /*!
3 @file isl12022m.c
4 @author K. Townsend (microBuilder.eu)
5
6 @brief Drivers for the ISL12022M RTC
7
8 @section DESCRIPTION
9
10 The ISL12022M is an I2C RTC with 128 bytes battery-backed up SRAM.
11
12 @section LICENSE
13
14 Software License Agreement (BSD License)
15
16 Copyright (c) 2010, microBuilder SARL
17 All rights reserved.
18
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions are met:
21 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 2. Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26 3. Neither the name of the copyright holders nor the
27 names of its contributors may be used to endorse or promote products
28 derived from this software without specific prior written permission.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41 /**************************************************************************/
42 #include "isl12022m.h"
43 #include "core/systick/systick.h"
44
45 extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
46 extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
47 extern volatile uint32_t I2CReadLength, I2CWriteLength;
48
49 uint8_t monthday[12]={31,28,31,30,31,30,31,31,30,31,30,31};
50
51 static bool _isl12022mInitialised = false;
52
53 /**************************************************************************/
54 /*!
55 @brief Standard decimal to binary coded decimal
56 */
57 /**************************************************************************/
58 uint8_t isl12022mDecToBCD(uint8_t val)
59 {
60 return ( (val/10*16) + (val%10) );
61 }
62
63 /**************************************************************************/
64 /*!
65 @brief Binary coded decimal to standard decimal
66 */
67 /**************************************************************************/
68 uint8_t isl12022mBCDToDec(uint8_t val)
69 {
70 return ( (val/16*10) + (val%16) );
71 }
72
73 /**************************************************************************/
74 /*!
75 @brief Writes an 8 bit value
76 */
77 /**************************************************************************/
78 isl12022mError_t isl12022mWrite8 (uint8_t address, uint8_t reg, uint32_t value)
79 {
80 // Clear write buffers
81 uint32_t i;
82 for ( i = 0; i < I2C_BUFSIZE; i++ )
83 {
84 I2CMasterBuffer[i] = 0x00;
85 }
86
87 I2CWriteLength = 3;
88 I2CReadLength = 0;
89 I2CMasterBuffer[0] = address;
90 I2CMasterBuffer[1] = reg; // Command register
91 I2CMasterBuffer[2] = (value & 0xFF); // Value to write
92 i2cEngine();
93 return ISL12022M_ERROR_OK;
94 }
95
96 /**************************************************************************/
97 /*!
98 @brief Reads x bytes into a buffer
99 */
100 /**************************************************************************/
101 isl12022mError_t isl12022mReadBuffer(uint8_t address, uint8_t reg, uint8_t *buffer, uint32_t len)
102 {
103 if (len > I2C_BUFSIZE)
104 return ISL12022M_ERROR_I2C_BUFFEROVERFLOW;
105
106 // Clear write buffers
107 uint32_t i;
108 for ( i = 0; i < I2C_BUFSIZE; i++ )
109 {
110 I2CMasterBuffer[i] = 0x00;
111 }
112
113 I2CWriteLength = 2;
114 I2CReadLength = len;
115 I2CMasterBuffer[0] = address;
116 I2CMasterBuffer[1] = reg; // Command register
117 // Append address w/read bit
118 I2CMasterBuffer[2] = address | ISL12022M_READBIT;
119 i2cEngine();
120
121 // Push response into buffer
122 for ( i = 0; i < len; i++ )
123 {
124 buffer[i] = I2CSlaveBuffer[i];
125 }
126
127 return ISL12022M_ERROR_OK;
128 }
129
130 /**************************************************************************/
131 /*!
132 @brief Initialises the I2C block
133 */
134 /**************************************************************************/
135 isl12022mError_t isl12022mInit(void)
136 {
137 isl12022mError_t error = ISL12022M_ERROR_OK;
138 uint8_t buffer[1];
139
140 // Initialise I2C
141 if (i2cInit(I2CMASTER) == false)
142 {
143 return ISL12022M_ERROR_I2C_INIT; /* Fatal error */
144 }
145
146 // Make sure write is enabled on the ISL12202M (factory default = disabled)
147 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_INT, buffer, sizeof(buffer));
148 if (!error)
149 {
150 if (!(buffer[0] & ISL12022M_INT_WRITEENABLE))
151 {
152 // Write is not enabled on the RTC ... enable it now
153 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_INT, buffer[0] | ISL12022M_INT_WRITEENABLE);
154 }
155 _isl12022mInitialised = true;
156 }
157
158 return error;
159 }
160
161 /**************************************************************************/
162 /*!
163 @brief Gets the current date/time from the RTC
164
165 @section EXAMPLE
166
167 @code
168 #include "drivers/rtc/isl12022m.h"
169 ...
170 isl12022mInit();
171
172 // Set the time to 12 June 2011 @ 11:59:30
173 isl12022mSetTime(0, 11, 6, 12, 11, 59, 30);
174
175 // Wait 5 seconds
176 systickDelay(5000);
177
178 // Display the current time
179 isl12022mTime_t time;
180 isl12022mGetTime(&time);
181 printf("DW:%d, Y:%d, M:%d, D:%d, H:%d, M:%d, S:%d\r\n",
182 time.dayofweek,
183 time.year,
184 time.month,
185 time.day,
186 time.hour,
187 time.minute,
188 time.second);
189 @endcode
190 */
191 /**************************************************************************/
192 isl12022mError_t isl12022mGetTime(isl12022mTime_t *time)
193 {
194 isl12022mError_t error = ISL12022M_ERROR_OK;
195 uint8_t buffer[9];
196
197 if (!_isl12022mInitialised)
198 {
199 error = isl12022mInit();
200 if (error) return error;
201 }
202
203 // Read 9 bytes at once into buffer
204 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS,
205 ISL12022M_REG_RTC_SC,
206 buffer, sizeof(buffer));
207
208 if (!error)
209 {
210 // Check status register
211 if (buffer[7] & (ISL12022M_STATUS_LOWBATT85 | ISL12022M_STATUS_LOWBATT75))
212 {
213 // Set low battery flag to indicate that the RTC value may not be accurate
214 error = ISL12022M_ERROR_RTC_LOWBATT;
215 }
216
217 time->second = isl12022mBCDToDec(buffer[0]);
218 time->minute = isl12022mBCDToDec(buffer[1]);
219 time->hour = buffer[2] & 0x1F; // 0x3F;
220 time->day = buffer[3] & 0x3F;
221 time->month = buffer[4] & 0x1F;
222 time->year = buffer[5];
223 time->dayofweek = buffer[6] & 0x07;
224 time->status = buffer[7];
225 time->interrupt = buffer[8];
226 }
227
228 return error;
229 }
230
231 /**************************************************************************/
232 /*!
233 @brief Sets the current date/time from the RTC
234
235 @section EXAMPLE
236
237 @code
238 #include "drivers/rtc/isl12022m.h"
239 ...
240 isl12022mInit();
241
242 // Set the time to 12 June 2011 @ 11:59:30
243 isl12022mSetTime(0, 11, 6, 12, 11, 59, 30);
244
245 // Wait 5 seconds
246 systickDelay(5000);
247
248 // Display the current time
249 isl12022mTime_t time;
250 isl12022mGetTime(&time);
251 printf("DW:%d, Y:%d, M:%d, D:%d, H:%d, M:%d, S:%d\r\n",
252 time.dayofweek,
253 time.year,
254 time.month,
255 time.day,
256 time.hour,
257 time.minute,
258 time.second);
259 @endcode
260 */
261 /**************************************************************************/
262 isl12022mError_t isl12022mSetTime(uint8_t dayofweek, uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
263 {
264 isl12022mError_t error = ISL12022M_ERROR_OK;
265
266 if (!_isl12022mInitialised)
267 {
268 error = isl12022mInit();
269 if (error) return error;
270 }
271
272 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_SC, isl12022mDecToBCD(second));
273 if (error) return error;
274 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_MN, isl12022mDecToBCD(minute));
275 if (error) return error;
276 // Always append military flag to hour (24 hour only)
277 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_HR, hour & 0x3F) | ISL12022M_HR_MILITARY;
278 if (error) return error;
279 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_DT, day & 0x3F);
280 if (error) return error;
281 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_MO, month & 0x1F);
282 if (error) return error;
283 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_YR, year);
284 if (error) return error;
285 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_DW, dayofweek & 0x07);
286 if (error) return error;
287
288 return error;
289 }
290
291 /**************************************************************************/
292 /*!
293 @brief Reads the current temperature from the ISL12022
294
295 @section EXAMPLE
296
297 @code
298 #include "drivers/rtc/isl12022m.h"
299 ...
300 isl12022mInit();
301
302 uint32_t temperature;
303 isl12022mGetTemp(&temperature);
304 printf("Temperature: %u C\r\n", temperature);
305
306 @endcode
307 */
308 /**************************************************************************/
309 isl12022mError_t isl12022mGetTemp(uint8_t *celsius)
310 {
311 isl12022mError_t error = ISL12022M_ERROR_OK;
312 uint8_t buffer[2];
313 uint32_t temp;
314
315 if (!_isl12022mInitialised)
316 {
317 error = isl12022mInit();
318 if (error) return error;
319 }
320
321 // Enable temperature sensing if required
322 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_BETA, buffer, 1);
323 if (!error)
324 {
325 if (!(buffer[0] & ISL12022M_BETA_TEMPENABLE))
326 {
327 // Temp sensor is not enabled ... enable it now
328 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_BETA, buffer[0] | ISL12022M_BETA_TEMPENABLE);
329 if (error)
330 return error;
331 }
332 }
333
334 // Wait 100ms for conversion to complete
335 systickDelay(100);
336 // Read low and high temp bytes (0x28 and 0x29)
337 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS, ISL12022M_REG_TEMP_TKOL, buffer, 2);
338 if (error)
339 return error;
340 // Convert value to degrees celsius (value/2 - 273 = degrees C)
341 temp = ((buffer[0]) | (buffer[1] << 8)) / 2 - 273;
342 *celsius = (uint8_t)temp & 0xFF;
343
344 return error;
345 }
This page took 0.076822 seconds and 5 git commands to generate.