Upgrade to v0.92
[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 uint32_t i;
50 uint8_t monthday[12]={31,28,31,30,31,30,31,31,30,31,30,31};
51
52 static bool _isl12022mInitialised = false;
53
54 /**************************************************************************/
55 /*!
56 @brief Standard decimal to binary coded decimal
57 */
58 /**************************************************************************/
59 uint8_t isl12022mDecToBCD(uint8_t val)
60 {
61 return ( (val/10*16) + (val%10) );
62 }
63
64 /**************************************************************************/
65 /*!
66 @brief Binary coded decimal to standard decimal
67 */
68 /**************************************************************************/
69 uint8_t isl12022mBCDToDec(uint8_t val)
70 {
71 return ( (val/16*10) + (val%16) );
72 }
73
74 /**************************************************************************/
75 /*!
76 @brief Writes an 8 bit value
77 */
78 /**************************************************************************/
79 isl12022mError_t isl12022mWrite8 (uint8_t address, uint8_t reg, uint32_t value)
80 {
81 // Clear write buffers
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 for ( i = 0; i < I2C_BUFSIZE; i++ )
108 {
109 I2CMasterBuffer[i] = 0x00;
110 }
111
112 I2CWriteLength = 2;
113 I2CReadLength = len;
114 I2CMasterBuffer[0] = address;
115 I2CMasterBuffer[1] = reg; // Command register
116 // Append address w/read bit
117 I2CMasterBuffer[2] = address | ISL12022M_READBIT;
118 i2cEngine();
119
120 // Push response into buffer
121 for ( i = 0; i < len; i++ )
122 {
123 buffer[i] = I2CSlaveBuffer[i];
124 }
125
126 return ISL12022M_ERROR_OK;
127 }
128
129 /**************************************************************************/
130 /*!
131 @brief Initialises the I2C block
132 */
133 /**************************************************************************/
134 isl12022mError_t isl12022mInit(void)
135 {
136 isl12022mError_t error = ISL12022M_ERROR_OK;
137 uint8_t buffer[1];
138
139 // Initialise I2C
140 if (i2cInit(I2CMASTER) == false)
141 {
142 return ISL12022M_ERROR_I2C_INIT; /* Fatal error */
143 }
144
145 // Make sure write is enabled on the ISL12202M (factory default = disabled)
146 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_INT, buffer, sizeof(buffer));
147 if (!error)
148 {
149 if (!(buffer[0] & ISL12022M_INT_WRITEENABLE))
150 {
151 // Write is not enabled on the RTC ... enable it now
152 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_INT, buffer[0] | ISL12022M_INT_WRITEENABLE);
153 }
154 _isl12022mInitialised = true;
155 }
156
157 return error;
158 }
159
160 /**************************************************************************/
161 /*!
162 @brief Gets the current date/time from the RTC
163
164 @section EXAMPLE
165
166 @code
167 #include "drivers/rtc/isl12022m.h"
168 ...
169 isl12022mInit();
170
171 // Set the time to 12 June 2011 @ 11:59:30
172 isl12022mSetTime(0, 11, 6, 12, 11, 59, 30);
173
174 // Wait 5 seconds
175 systickDelay(5000);
176
177 // Display the current time
178 isl12022mTime_t time;
179 isl12022mGetTime(&time);
180 printf("DW:%d, Y:%d, M:%d, D:%d, H:%d, M:%d, S:%d\r\n",
181 time.dayofweek,
182 time.year,
183 time.month,
184 time.day,
185 time.hour,
186 time.minute,
187 time.second);
188 @endcode
189 */
190 /**************************************************************************/
191 isl12022mError_t isl12022mGetTime(isl12022mTime_t *time)
192 {
193 isl12022mError_t error = ISL12022M_ERROR_OK;
194 uint8_t buffer[9];
195
196 if (!_isl12022mInitialised)
197 {
198 error = isl12022mInit();
199 if (error) return error;
200 }
201
202 // Read 9 bytes at once into buffer
203 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS,
204 ISL12022M_REG_RTC_SC,
205 buffer, sizeof(buffer));
206
207 if (!error)
208 {
209 // Check status register
210 if (buffer[7] & (ISL12022M_STATUS_LOWBATT85 | ISL12022M_STATUS_LOWBATT75))
211 {
212 // Set low battery flag to indicate that the RTC value may not be accurate
213 error = ISL12022M_ERROR_RTC_LOWBATT;
214 }
215
216 time->second = isl12022mBCDToDec(buffer[0]);
217 time->minute = isl12022mBCDToDec(buffer[1]);
218 time->hour = buffer[2] & 0x1F; // 0x3F;
219 time->day = buffer[3] & 0x3F;
220 time->month = buffer[4] & 0x1F;
221 time->year = buffer[5];
222 time->dayofweek = buffer[6] & 0x07;
223 time->status = buffer[7];
224 time->interrupt = buffer[8];
225 }
226
227 return error;
228 }
229
230 /**************************************************************************/
231 /*!
232 @brief Sets the current date/time from the RTC
233
234 @section EXAMPLE
235
236 @code
237 #include "drivers/rtc/isl12022m.h"
238 ...
239 isl12022mInit();
240
241 // Set the time to 12 June 2011 @ 11:59:30
242 isl12022mSetTime(0, 11, 6, 12, 11, 59, 30);
243
244 // Wait 5 seconds
245 systickDelay(5000);
246
247 // Display the current time
248 isl12022mTime_t time;
249 isl12022mGetTime(&time);
250 printf("DW:%d, Y:%d, M:%d, D:%d, H:%d, M:%d, S:%d\r\n",
251 time.dayofweek,
252 time.year,
253 time.month,
254 time.day,
255 time.hour,
256 time.minute,
257 time.second);
258 @endcode
259 */
260 /**************************************************************************/
261 isl12022mError_t isl12022mSetTime(uint8_t dayofweek, uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
262 {
263 isl12022mError_t error = ISL12022M_ERROR_OK;
264
265 if (!_isl12022mInitialised)
266 {
267 error = isl12022mInit();
268 if (error) return error;
269 }
270
271 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_SC, isl12022mDecToBCD(second));
272 if (error) return error;
273 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_MN, isl12022mDecToBCD(minute));
274 if (error) return error;
275 // Always append military flag to hour (24 hour only)
276 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_HR, hour & 0x3F) | ISL12022M_HR_MILITARY;
277 if (error) return error;
278 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_DT, day & 0x3F);
279 if (error) return error;
280 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_MO, month & 0x1F);
281 if (error) return error;
282 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_YR, year);
283 if (error) return error;
284 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_RTC_DW, dayofweek & 0x07);
285 if (error) return error;
286
287 return error;
288 }
289
290 /**************************************************************************/
291 /*!
292 @brief Reads the current temperature from the ISL12022
293
294 @section EXAMPLE
295
296 @code
297 #include "drivers/rtc/isl12022m.h"
298 ...
299 isl12022mInit();
300
301 uint32_t temperature;
302 isl12022mGetTemp(&temperature);
303 printf("Temperature: %u C\r\n", temperature);
304
305 @endcode
306 */
307 /**************************************************************************/
308 isl12022mError_t isl12022mGetTemp(uint8_t *celsius)
309 {
310 isl12022mError_t error = ISL12022M_ERROR_OK;
311 uint8_t buffer[2];
312 uint32_t temp;
313
314 if (!_isl12022mInitialised)
315 {
316 error = isl12022mInit();
317 if (error) return error;
318 }
319
320 // Enable temperature sensing if required
321 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_BETA, buffer, 1);
322 if (!error)
323 {
324 if (!(buffer[0] & ISL12022M_BETA_TEMPENABLE))
325 {
326 // Temp sensor is not enabled ... enable it now
327 error = isl12022mWrite8(ISL12022M_RTC_ADDRESS, ISL12022M_REG_CSR_BETA, buffer[0] | ISL12022M_BETA_TEMPENABLE);
328 if (error)
329 return error;
330 }
331 }
332
333 // Wait 100ms for conversion to complete
334 systickDelay(100);
335 // Read low and high temp bytes (0x28 and 0x29)
336 error = isl12022mReadBuffer(ISL12022M_RTC_ADDRESS, ISL12022M_REG_TEMP_TKOL, buffer, 2);
337 if (error)
338 return error;
339 // Convert value to degrees celsius (value/2 - 273 = degrees C)
340 temp = ((buffer[0]) | (buffer[1] << 8)) / 2 - 273;
341 *celsius = (uint8_t)temp & 0xFF;
342
343 return error;
344 }
This page took 0.075029 seconds and 5 git commands to generate.