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