Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / OWI.c
1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
2 /*! \file ********************************************************************\r
3  *\r
4  * \brief\r
5  *      Functions for 1-Wire(R) bus communication\r
6  *\r
7  *      High level functions for transmission of full bytes on the 1-Wire(R)\r
8  *      bus and implementations of ROM commands.\n\r
9  *      Polled software only implementation of the basic bit-level signalling\r
10  *      in the 1-Wire(R) protocol.\n\r
11  *      Includes functions for computing and checking CRC8 & 16 values of data\r
12  *      sets, and of 64 bit ROM identifiers.\r
13  *      Supported devices:  All AVRs.\r
14  *\r
15  * \par Application Note:\r
16  *      AVR458: Charging Li-Ion Batteries with BC100\n\r
17  *      AVR463: Charging NiMH Batteries with BC100\n\r
18  *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
19  *\r
20  * \par Documentation:\r
21  *      For comprehensive code documentation, supported compilers, compiler\r
22  *      settings and supported devices see readme.html\r
23  *\r
24  * \author\r
25  *      Atmel Corporation: http://www.atmel.com \n\r
26  *      Support email: avr@atmel.com \n\r
27  *      Original author: \n\r
28  *\r
29  * $Name$\r
30  * $Revision: 2299 $\r
31  * $RCSfile$\r
32  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
33  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
34 ****************************************************************************/\r
35 \r
36 #include <ioavr.h>\r
37 #include <inavr.h>\r
38 \r
39 #include "OWI.h"\r
40 \r
41 \r
42 //******************************************************************************\r
43 // Functions\r
44 //******************************************************************************\r
45 /*! \brief Initialization of the one wire bus(es). (Software only driver)\r
46  *  \r
47  *  This function initializes the 1-Wire bus(es) by releasing it and\r
48  *  waiting until any presence signals are finished.\r
49  *\r
50  *  \param  pins    A bitmask of the buses to initialize.\r
51  */\r
52 void OWI_Init(unsigned char pins){\r
53         OWI_RELEASE_BUS(pins);\r
54         // The first rising edge can be interpreted by a slave as the end of a\r
55         // Reset-pulse. Delay for the required reset recovery time (H) to be \r
56         // sure that the real reset is interpreted correctly.\r
57         __delay_cycles(OWI_DELAY_H_STD_MODE);\r
58 }\r
59 \r
60 \r
61 /*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
62  *\r
63  *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
64  *  bus.\r
65  *\r
66  *  \param  pins    A bitmask of the buses to write to.\r
67  */\r
68 void OWI_WriteBit1(unsigned char pins){\r
69         unsigned char intState;\r
70         \r
71         // Disable interrupts.\r
72         intState = __save_interrupt();\r
73         __disable_interrupt();\r
74         \r
75         // Drive bus low and delay.\r
76         OWI_PULL_BUS_LOW(pins);\r
77         __delay_cycles(OWI_DELAY_A_STD_MODE);\r
78         \r
79         // Release bus and delay.\r
80         OWI_RELEASE_BUS(pins);\r
81         __delay_cycles(OWI_DELAY_B_STD_MODE);\r
82         \r
83         // Restore interrupts.\r
84         __restore_interrupt(intState);\r
85 }\r
86 \r
87 /*! \brief  Write a '0' to the bus(es). (Software only driver)\r
88  *\r
89  *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
90  *  bus.\r
91  *\r
92  *  \param  pins    A bitmask of the buses to write to.\r
93  */\r
94 void OWI_WriteBit0(unsigned char pins)\r
95 {\r
96         unsigned char intState;\r
97         \r
98         // Disable interrupts.\r
99         intState = __save_interrupt();\r
100         __disable_interrupt();\r
101         \r
102         // Drive bus low and delay.\r
103         OWI_PULL_BUS_LOW(pins);\r
104         __delay_cycles(OWI_DELAY_C_STD_MODE);\r
105         \r
106         // Release bus and delay.\r
107         OWI_RELEASE_BUS(pins);\r
108         __delay_cycles(OWI_DELAY_D_STD_MODE);\r
109         \r
110         // Restore interrupts.\r
111         __restore_interrupt(intState);\r
112 }\r
113 \r
114 /*! \brief  Read a bit from the bus(es). (Software only driver)\r
115  *\r
116  *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
117  *\r
118  *  \param  pins    A bitmask of the bus(es) to read from.\r
119  *\r
120  *  \return A bitmask of the buses where a '1' was read.\r
121  */\r
122 unsigned char OWI_ReadBit(unsigned char pins)\r
123 {\r
124         unsigned char intState;\r
125         unsigned char bitsRead;\r
126         \r
127         // Disable interrupts.\r
128         intState = __save_interrupt();\r
129         __disable_interrupt();\r
130         \r
131         // Drive bus low and delay.\r
132         OWI_PULL_BUS_LOW(pins);\r
133         __delay_cycles(OWI_DELAY_A_STD_MODE);\r
134         \r
135         // Release bus and delay.\r
136         OWI_RELEASE_BUS(pins);\r
137         __delay_cycles(OWI_DELAY_E_STD_MODE);\r
138         \r
139         // Sample bus and delay.\r
140         bitsRead = OWI_PIN & pins;\r
141         __delay_cycles(OWI_DELAY_F_STD_MODE);\r
142         \r
143         // Restore interrupts.\r
144         __restore_interrupt(intState);\r
145         \r
146         return bitsRead;\r
147 }\r
148 \r
149 \r
150 /*! \brief  Send a Reset signal and listen for Presence signal. (software\r
151  *  only driver)\r
152  *\r
153  *  Generates the waveform for transmission of a Reset pulse on the \r
154  *  1-Wire(R) bus and listens for presence signals.\r
155  *\r
156  *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
157  *\r
158  *  \return A bitmask of the buses where a presence signal was detected.\r
159  */\r
160 unsigned char OWI_DetectPresence(unsigned char pins)\r
161 {\r
162         unsigned char intState;\r
163         unsigned char presenceDetected;\r
164         \r
165         // Disable interrupts.\r
166         intState = __save_interrupt();\r
167         __disable_interrupt();\r
168         \r
169         // Drive bus low and delay.\r
170         OWI_PULL_BUS_LOW(pins);\r
171         __delay_cycles(OWI_DELAY_H_STD_MODE);\r
172         \r
173         // Release bus and delay.\r
174         OWI_RELEASE_BUS(pins);\r
175         __delay_cycles(OWI_DELAY_I_STD_MODE);\r
176         \r
177         // Sample bus to detect presence signal and delay.\r
178         presenceDetected = ((~OWI_PIN) & pins);\r
179         __delay_cycles(OWI_DELAY_J_STD_MODE);\r
180         \r
181         // Restore interrupts.\r
182         __restore_interrupt(intState);\r
183         \r
184         return presenceDetected;\r
185 }\r
186 \r
187 \r
188 /*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
189  *  \r
190  *  This function automates the task of sending a complete byte\r
191  *  of data on the 1-Wire bus(es).\r
192  *\r
193  *  \param  data    The data to send on the bus(es).\r
194  *  \r
195  *  \param  pins    A bitmask of the buses to send the data to.\r
196  */\r
197 void OWI_SendByte(unsigned char data, unsigned char pins)\r
198 {\r
199         unsigned char temp;\r
200         unsigned char i;\r
201         \r
202         // Do once for each bit\r
203         for (i = 0; i < 8; i++) {\r
204                 // Determine if LSB is '0' or '1' and transmit corresponding\r
205                 // waveform on the bus.\r
206                 temp = data & 0x01;\r
207                 \r
208                 if (temp) {\r
209                         OWI_WriteBit1(pins);\r
210                 } else {\r
211                         OWI_WriteBit0(pins);\r
212                 }\r
213         \r
214                 data >>= 1;  // Right shift the data to get next bit.\r
215         }\r
216 }\r
217 \r
218 \r
219 /*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
220  *\r
221  *  This function automates the task of receiving a complete byte \r
222  *  of data from the 1-Wire bus.\r
223  *\r
224  *  \param  pin     A bitmask of the bus to read from.\r
225  *  \r
226  *  \return     The byte read from the bus.\r
227  */\r
228 unsigned char OWI_ReceiveByte(unsigned char pin)\r
229 {\r
230         unsigned char data;\r
231         unsigned char i;\r
232         \r
233         // Clear the temporary input variable.\r
234         data = 0x00;\r
235         \r
236         // Do once for each bit\r
237         for (i = 0; i < 8; i++) {\r
238                 // Shift temporary input variable right.\r
239                 data >>= 1;\r
240                 \r
241                 // Set the MSB if a '1' value is read from the bus.\r
242                 // Leave as it is ('0') else.\r
243                 if (OWI_ReadBit(pin)) {\r
244                         data |= 0x80;\r
245                 }\r
246         }\r
247         \r
248         return data;\r
249 }\r
250 \r
251 \r
252 /*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
253  *\r
254  *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
255  */\r
256 void OWI_SkipRom(unsigned char pins)\r
257 {\r
258         // Send the SKIP ROM command on the bus.\r
259         OWI_SendByte(OWI_ROM_SKIP, pins);\r
260 }\r
261 \r
262 \r
263 /*! \brief  Sends the READ ROM command and reads back the ROM id.\r
264  *\r
265  *  \param  romValue    A pointer where the id will be placed.\r
266  *\r
267  *  \param  pin     A bitmask of the bus to read from.\r
268  */\r
269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
270 {\r
271         unsigned char bytesLeft = 8;\r
272         \r
273         // Send the READ ROM command on the bus.\r
274         OWI_SendByte(OWI_ROM_READ, pin);\r
275         \r
276         // Do 8 times.\r
277         while (bytesLeft > 0) {\r
278                 // Place the received data in memory.\r
279                 *romValue++ = OWI_ReceiveByte(pin);\r
280                 bytesLeft--;\r
281         }\r
282 }\r
283 \r
284 \r
285 /*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
286  *\r
287  *  \param  romValue    A pointer to the ID to match against.\r
288  *\r
289  *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
290  */\r
291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
292 {\r
293         unsigned char bytesLeft = 8;   \r
294         \r
295         // Send the MATCH ROM command.\r
296         OWI_SendByte(OWI_ROM_MATCH, pins);\r
297         \r
298         // Do once for each byte.\r
299         while (bytesLeft > 0) {\r
300                 // Transmit 1 byte of the ID to match.\r
301                 OWI_SendByte(*romValue++, pins);\r
302                 bytesLeft--;\r
303         }\r
304 }\r
305 \r
306 \r
307 /*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
308  *          1-Wire(R) bus.\r
309  *\r
310  *  \param  bitPattern      A pointer to an 8 byte char array where the \r
311  *                          discovered identifier will be placed. When \r
312  *                          searching for several slaves, a copy of the \r
313  *                          last found identifier should be supplied in \r
314  *                          the array, or the search will fail.\r
315  *\r
316  *  \param  lastDeviation   The bit position where the algorithm made a \r
317  *                          choice the last time it was run. This argument \r
318  *                          should be 0 when a search is initiated. Supplying \r
319  *                          the return argument of this function when calling \r
320  *                          repeatedly will go through the complete slave \r
321  *                          search.\r
322  *\r
323  *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
324  *\r
325  *  \return The last bit position where there was a discrepancy between slave\r
326  *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
327  *  if an error was detected (e.g. a device was connected to the bus during the\r
328  *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
329  *  discovered.\r
330  *\r
331  *  \note   See main.c for an example of how to utilize this function.\r
332  */\r
333 unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
334                                                 unsigned char lastDeviation, unsigned char pin)\r
335 {\r
336         unsigned char currentBit = 1;\r
337         unsigned char newDeviation = 0;\r
338         unsigned char bitMask = 0x01;\r
339         unsigned char bitA;\r
340         unsigned char bitB;\r
341         \r
342         // Send SEARCH ROM command on the bus.\r
343         OWI_SendByte(OWI_ROM_SEARCH, pin);\r
344         \r
345         // Walk through all 64 bits.\r
346         while (currentBit <= 64) {\r
347                 // Read bit from bus twice.\r
348                 bitA = OWI_ReadBit(pin);\r
349                 bitB = OWI_ReadBit(pin);\r
350                 \r
351                 if (bitA && bitB) {\r
352                         // Both bits 1 (Error).\r
353                         newDeviation = OWI_ROM_SEARCH_FAILED;\r
354                         return newDeviation;\r
355                 } else if (bitA ^ bitB) {\r
356                         // Bits A and B are different. All devices have the same bit here.\r
357                         // Set the bit in bitPattern to this value.\r
358                         if (bitA) {\r
359                                 (*bitPattern) |= bitMask;\r
360                         } else {\r
361                                 (*bitPattern) &= ~bitMask;\r
362                         }\r
363                 } else {\r
364                         // If this is where a choice was made the last time,\r
365                         // a '1' bit is selected this time.\r
366                         if (currentBit == lastDeviation) {\r
367                                 (*bitPattern) |= bitMask;\r
368                         }\r
369                         \r
370                         // For the rest of the id, '0' bits are selected when\r
371                         // discrepancies occur.\r
372                         else if (currentBit > lastDeviation) {\r
373                                 (*bitPattern) &= ~bitMask;\r
374                                 newDeviation = currentBit;\r
375                         }\r
376                         \r
377                         // If current bit in bit pattern = 0, then this is\r
378                         // out new deviation.\r
379                         else if ( !(*bitPattern & bitMask)) {\r
380                                 newDeviation = currentBit;\r
381                         }\r
382                         \r
383                 // IF the bit is already 1, do nothing.\r
384                         else {\r
385                         }\r
386                 }\r
387                 \r
388                 // Send the selected bit to the bus.\r
389                 if ((*bitPattern) & bitMask) {\r
390                         OWI_WriteBit1(pin);\r
391                 } else {\r
392                         OWI_WriteBit0(pin);\r
393                 }\r
394                 \r
395                 // Increment current bit.    \r
396                 currentBit++;\r
397                 \r
398                 // Adjust bitMask and bitPattern pointer.    \r
399                 bitMask <<= 1;\r
400                 if (!bitMask) {\r
401                         bitMask = 0x01;\r
402                         bitPattern++;\r
403                 }\r
404         }\r
405         \r
406         return newDeviation;\r
407 }\r
408 \r
409 \r
410 /* Functions for handling CRC */\r
411 /*! \brief  Compute the CRC8 value of a data set.\r
412  *\r
413  *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
414  *  as inital value for the CRC.\r
415  *\r
416  *  \param  inData  One byte of data to compute CRC from.\r
417  *\r
418  *  \param  seed    The starting value of the CRC.\r
419  *\r
420  *  \return The CRC8 of inData with seed as initial value.\r
421  *\r
422  *  \note   Setting seed to 0 computes the crc8 of the inData.\r
423  *\r
424  *  \note   Constantly passing the return value of this function \r
425  *          As the seed argument computes the CRC8 value of a\r
426  *          longer string of data.\r
427  */\r
428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
429 {\r
430         unsigned char bitsLeft;\r
431         unsigned char temp;\r
432         \r
433         for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
434                 temp = ((seed ^ inData) & 0x01);\r
435                 \r
436                 if (temp == 0) {\r
437                 seed >>= 1;\r
438                 } else {\r
439                         seed ^= 0x18;\r
440                         seed >>= 1;\r
441                         seed |= 0x80;\r
442                 }\r
443                 \r
444                 inData >>= 1;\r
445         }\r
446         return seed;    \r
447 }\r
448 \r
449 \r
450 /*! \brief  Compute the CRC16 value of a data set.\r
451  *\r
452  *  This function will compute the CRC16 of inData using seed\r
453  *  as inital value for the CRC.\r
454  *\r
455  *  \param  inData  One byte of data to compute CRC from.\r
456  *\r
457  *  \param  seed    The starting value of the CRC.\r
458  *\r
459  *  \return The CRC16 of inData with seed as initial value.\r
460  *\r
461  *  \note   Setting seed to 0 computes the crc16 of the inData.\r
462  *\r
463  *  \note   Constantly passing the return value of this function \r
464  *          As the seed argument computes the CRC16 value of a\r
465  *          longer string of data.\r
466  */\r
467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
468 {\r
469         unsigned char bitsLeft;\r
470         unsigned char temp;\r
471         \r
472         for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
473                 temp = ((seed ^ inData) & 0x01);\r
474                 \r
475                 if (temp == 0) {\r
476                         seed >>= 1;\r
477           } else {\r
478                         seed ^= 0x4002;\r
479                         seed >>= 1;\r
480                         seed |= 0x8000;\r
481                 }\r
482 \r
483                 inData >>= 1;\r
484         }\r
485         \r
486         return seed;    \r
487 }\r
488 \r
489 \r
490 /*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
491  *  \r
492  *  This function computes the CRC8 value of the first 56 bits of a\r
493  *  64 bit identifier. It then checks the calculated value against the\r
494  *  CRC value stored in ROM.\r
495  *\r
496  *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
497  *\r
498  *  \retval OWI_CRC_OK      The CRC's matched.\r
499  *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
500  */\r
501 unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
502 {\r
503         unsigned char i;\r
504         unsigned char crc8 = 0;\r
505         \r
506         for (i = 0; i < 7; i++) {\r
507                 crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
508                 romValue++;\r
509         }\r
510         \r
511         if (crc8 == (*romValue)) {\r
512                 return OWI_CRC_OK;\r
513         }\r
514         \r
515         return OWI_CRC_ERROR;\r
516 }\r