1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
2 /*! \file ********************************************************************
\r
5 * Functions for 1-Wire(R) bus communication
\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
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
20 * \par Documentation:
\r
21 * For comprehensive code documentation, supported compilers, compiler
\r
22 * settings and supported devices see readme.html
\r
25 * Atmel Corporation: http://www.atmel.com \n
\r
26 * Support email: avr@atmel.com \n
\r
27 * Original author: \n
\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
42 //******************************************************************************
\r
44 //******************************************************************************
\r
45 /*! \brief Initialization of the one wire bus(es). (Software only driver)
\r
47 * This function initializes the 1-Wire bus(es) by releasing it and
\r
48 * waiting until any presence signals are finished.
\r
50 * \param pins A bitmask of the buses to initialize.
\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
61 /*! \brief Write a '1' bit to the bus(es). (Software only driver)
\r
63 * Generates the waveform for transmission of a '1' bit on the 1-Wire
\r
66 * \param pins A bitmask of the buses to write to.
\r
68 void OWI_WriteBit1(unsigned char pins){
\r
69 unsigned char intState;
\r
71 // Disable interrupts.
\r
72 intState = __save_interrupt();
\r
73 __disable_interrupt();
\r
75 // Drive bus low and delay.
\r
76 OWI_PULL_BUS_LOW(pins);
\r
77 __delay_cycles(OWI_DELAY_A_STD_MODE);
\r
79 // Release bus and delay.
\r
80 OWI_RELEASE_BUS(pins);
\r
81 __delay_cycles(OWI_DELAY_B_STD_MODE);
\r
83 // Restore interrupts.
\r
84 __restore_interrupt(intState);
\r
87 /*! \brief Write a '0' to the bus(es). (Software only driver)
\r
89 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R)
\r
92 * \param pins A bitmask of the buses to write to.
\r
94 void OWI_WriteBit0(unsigned char pins)
\r
96 unsigned char intState;
\r
98 // Disable interrupts.
\r
99 intState = __save_interrupt();
\r
100 __disable_interrupt();
\r
102 // Drive bus low and delay.
\r
103 OWI_PULL_BUS_LOW(pins);
\r
104 __delay_cycles(OWI_DELAY_C_STD_MODE);
\r
106 // Release bus and delay.
\r
107 OWI_RELEASE_BUS(pins);
\r
108 __delay_cycles(OWI_DELAY_D_STD_MODE);
\r
110 // Restore interrupts.
\r
111 __restore_interrupt(intState);
\r
114 /*! \brief Read a bit from the bus(es). (Software only driver)
\r
116 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).
\r
118 * \param pins A bitmask of the bus(es) to read from.
\r
120 * \return A bitmask of the buses where a '1' was read.
\r
122 unsigned char OWI_ReadBit(unsigned char pins)
\r
124 unsigned char intState;
\r
125 unsigned char bitsRead;
\r
127 // Disable interrupts.
\r
128 intState = __save_interrupt();
\r
129 __disable_interrupt();
\r
131 // Drive bus low and delay.
\r
132 OWI_PULL_BUS_LOW(pins);
\r
133 __delay_cycles(OWI_DELAY_A_STD_MODE);
\r
135 // Release bus and delay.
\r
136 OWI_RELEASE_BUS(pins);
\r
137 __delay_cycles(OWI_DELAY_E_STD_MODE);
\r
139 // Sample bus and delay.
\r
140 bitsRead = OWI_PIN & pins;
\r
141 __delay_cycles(OWI_DELAY_F_STD_MODE);
\r
143 // Restore interrupts.
\r
144 __restore_interrupt(intState);
\r
150 /*! \brief Send a Reset signal and listen for Presence signal. (software
\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
156 * \param pins A bitmask of the buses to send the Reset signal on.
\r
158 * \return A bitmask of the buses where a presence signal was detected.
\r
160 unsigned char OWI_DetectPresence(unsigned char pins)
\r
162 unsigned char intState;
\r
163 unsigned char presenceDetected;
\r
165 // Disable interrupts.
\r
166 intState = __save_interrupt();
\r
167 __disable_interrupt();
\r
169 // Drive bus low and delay.
\r
170 OWI_PULL_BUS_LOW(pins);
\r
171 __delay_cycles(OWI_DELAY_H_STD_MODE);
\r
173 // Release bus and delay.
\r
174 OWI_RELEASE_BUS(pins);
\r
175 __delay_cycles(OWI_DELAY_I_STD_MODE);
\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
181 // Restore interrupts.
\r
182 __restore_interrupt(intState);
\r
184 return presenceDetected;
\r
188 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es).
\r
190 * This function automates the task of sending a complete byte
\r
191 * of data on the 1-Wire bus(es).
\r
193 * \param data The data to send on the bus(es).
\r
195 * \param pins A bitmask of the buses to send the data to.
\r
197 void OWI_SendByte(unsigned char data, unsigned char pins)
\r
199 unsigned char temp;
\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
209 OWI_WriteBit1(pins);
\r
211 OWI_WriteBit0(pins);
\r
214 data >>= 1; // Right shift the data to get next bit.
\r
219 /*! \brief Receives one byte of data from the 1-Wire(R) bus.
\r
221 * This function automates the task of receiving a complete byte
\r
222 * of data from the 1-Wire bus.
\r
224 * \param pin A bitmask of the bus to read from.
\r
226 * \return The byte read from the bus.
\r
228 unsigned char OWI_ReceiveByte(unsigned char pin)
\r
230 unsigned char data;
\r
233 // Clear the temporary input variable.
\r
236 // Do once for each bit
\r
237 for (i = 0; i < 8; i++) {
\r
238 // Shift temporary input variable right.
\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
252 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es).
\r
254 * \param pins A bitmask of the buses to send the SKIP ROM command to.
\r
256 void OWI_SkipRom(unsigned char pins)
\r
258 // Send the SKIP ROM command on the bus.
\r
259 OWI_SendByte(OWI_ROM_SKIP, pins);
\r
263 /*! \brief Sends the READ ROM command and reads back the ROM id.
\r
265 * \param romValue A pointer where the id will be placed.
\r
267 * \param pin A bitmask of the bus to read from.
\r
269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin)
\r
271 unsigned char bytesLeft = 8;
\r
273 // Send the READ ROM command on the bus.
\r
274 OWI_SendByte(OWI_ROM_READ, pin);
\r
277 while (bytesLeft > 0) {
\r
278 // Place the received data in memory.
\r
279 *romValue++ = OWI_ReceiveByte(pin);
\r
285 /*! \brief Sends the MATCH ROM command and the ROM id to match against.
\r
287 * \param romValue A pointer to the ID to match against.
\r
289 * \param pins A bitmask of the buses to perform the MATCH ROM command on.
\r
291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins)
\r
293 unsigned char bytesLeft = 8;
\r
295 // Send the MATCH ROM command.
\r
296 OWI_SendByte(OWI_ROM_MATCH, pins);
\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
307 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the
\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
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
323 * \param pin A bit-mask of the bus to perform a ROM search on.
\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
331 * \note See main.c for an example of how to utilize this function.
\r
333 unsigned char OWI_SearchRom(unsigned char * bitPattern,
\r
334 unsigned char lastDeviation, unsigned char pin)
\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
342 // Send SEARCH ROM command on the bus.
\r
343 OWI_SendByte(OWI_ROM_SEARCH, pin);
\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
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
359 (*bitPattern) |= bitMask;
\r
361 (*bitPattern) &= ~bitMask;
\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
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
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
383 // IF the bit is already 1, do nothing.
\r
388 // Send the selected bit to the bus.
\r
389 if ((*bitPattern) & bitMask) {
\r
390 OWI_WriteBit1(pin);
\r
392 OWI_WriteBit0(pin);
\r
395 // Increment current bit.
\r
398 // Adjust bitMask and bitPattern pointer.
\r
406 return newDeviation;
\r
410 /* Functions for handling CRC */
\r
411 /*! \brief Compute the CRC8 value of a data set.
\r
413 * This function will compute the CRC8 or DOW-CRC of inData using seed
\r
414 * as inital value for the CRC.
\r
416 * \param inData One byte of data to compute CRC from.
\r
418 * \param seed The starting value of the CRC.
\r
420 * \return The CRC8 of inData with seed as initial value.
\r
422 * \note Setting seed to 0 computes the crc8 of the inData.
\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
428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)
\r
430 unsigned char bitsLeft;
\r
431 unsigned char temp;
\r
433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {
\r
434 temp = ((seed ^ inData) & 0x01);
\r
450 /*! \brief Compute the CRC16 value of a data set.
\r
452 * This function will compute the CRC16 of inData using seed
\r
453 * as inital value for the CRC.
\r
455 * \param inData One byte of data to compute CRC from.
\r
457 * \param seed The starting value of the CRC.
\r
459 * \return The CRC16 of inData with seed as initial value.
\r
461 * \note Setting seed to 0 computes the crc16 of the inData.
\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
467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)
\r
469 unsigned char bitsLeft;
\r
470 unsigned char temp;
\r
472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {
\r
473 temp = ((seed ^ inData) & 0x01);
\r
490 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier.
\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
496 * \param *romValue A pointer to an array holding a 64 bit identifier.
\r
498 * \retval OWI_CRC_OK The CRC's matched.
\r
499 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match.
\r
501 unsigned char OWI_CheckRomCRC(unsigned char *romValue)
\r
504 unsigned char crc8 = 0;
\r
506 for (i = 0; i < 7; i++) {
\r
507 crc8 = OWI_ComputeCRC8(*romValue, crc8);
\r
511 if (crc8 == (*romValue)) {
\r
515 return OWI_CRC_ERROR;
\r