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