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
37 #include <avr/interrupt.h>
\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
46 //******************************************************************************
\r
48 //******************************************************************************
\r
49 /*! \brief Initialization of the one wire bus(es). (Software only driver)
\r
51 * This function initializes the 1-Wire bus(es) by releasing it and
\r
52 * waiting until any presence signals are finished.
\r
54 * \param pins A bitmask of the buses to initialize.
\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
65 /*! \brief Write a '1' bit to the bus(es). (Software only driver)
\r
67 * Generates the waveform for transmission of a '1' bit on the 1-Wire
\r
70 * \param pins A bitmask of the buses to write to.
\r
72 void OWI_WriteBit1(unsigned char pins){
\r
73 unsigned char intState;
\r
75 // Disable interrupts.
\r
76 intState = SREG & SREG_I;
\r
79 // Drive bus low and delay.
\r
80 OWI_PULL_BUS_LOW(pins);
\r
81 _delay_cycles(OWI_DELAY_A_STD_MODE);
\r
83 // Release bus and delay.
\r
84 OWI_RELEASE_BUS(pins);
\r
85 _delay_cycles(OWI_DELAY_B_STD_MODE);
\r
87 // Restore interrupts.
\r
92 /*! \brief Write a '0' to the bus(es). (Software only driver)
\r
94 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R)
\r
97 * \param pins A bitmask of the buses to write to.
\r
99 void OWI_WriteBit0(unsigned char pins)
\r
101 unsigned char intState;
\r
103 // Disable interrupts.
\r
104 intState = SREG & SREG_I;
\r
107 // Drive bus low and delay.
\r
108 OWI_PULL_BUS_LOW(pins);
\r
109 _delay_cycles(OWI_DELAY_C_STD_MODE);
\r
111 // Release bus and delay.
\r
112 OWI_RELEASE_BUS(pins);
\r
113 _delay_cycles(OWI_DELAY_D_STD_MODE);
\r
115 // Restore interrupts.
\r
120 /*! \brief Read a bit from the bus(es). (Software only driver)
\r
122 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).
\r
124 * \param pins A bitmask of the bus(es) to read from.
\r
126 * \return A bitmask of the buses where a '1' was read.
\r
128 unsigned char OWI_ReadBit(unsigned char pins)
\r
130 unsigned char intState;
\r
131 unsigned char bitsRead;
\r
133 // Disable interrupts.
\r
134 intState = SREG & SREG_I;
\r
137 // Drive bus low and delay.
\r
138 OWI_PULL_BUS_LOW(pins);
\r
139 _delay_cycles(OWI_DELAY_A_STD_MODE);
\r
141 // Release bus and delay.
\r
142 OWI_RELEASE_BUS(pins);
\r
143 _delay_cycles(OWI_DELAY_E_STD_MODE);
\r
145 // Sample bus and delay.
\r
146 bitsRead = OWI_PIN & pins;
\r
147 _delay_cycles(OWI_DELAY_F_STD_MODE);
\r
149 // Restore interrupts.
\r
157 /*! \brief Send a Reset signal and listen for Presence signal. (software
\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
163 * \param pins A bitmask of the buses to send the Reset signal on.
\r
165 * \return A bitmask of the buses where a presence signal was detected.
\r
167 unsigned char OWI_DetectPresence(unsigned char pins)
\r
169 unsigned char intState;
\r
170 unsigned char presenceDetected;
\r
172 // Disable interrupts.
\r
173 intState = SREG & SREG_I;
\r
176 // Drive bus low and delay.
\r
177 OWI_PULL_BUS_LOW(pins);
\r
178 _delay_cycles(OWI_DELAY_H_STD_MODE);
\r
180 // Release bus and delay.
\r
181 OWI_RELEASE_BUS(pins);
\r
182 _delay_cycles(OWI_DELAY_I_STD_MODE);
\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
188 // Restore interrupts.
\r
192 return presenceDetected;
\r
196 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es).
\r
198 * This function automates the task of sending a complete byte
\r
199 * of data on the 1-Wire bus(es).
\r
201 * \param data The data to send on the bus(es).
\r
203 * \param pins A bitmask of the buses to send the data to.
\r
205 void OWI_SendByte(unsigned char data, unsigned char pins)
\r
207 unsigned char temp;
\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
217 OWI_WriteBit1(pins);
\r
219 OWI_WriteBit0(pins);
\r
222 data >>= 1; // Right shift the data to get next bit.
\r
227 /*! \brief Receives one byte of data from the 1-Wire(R) bus.
\r
229 * This function automates the task of receiving a complete byte
\r
230 * of data from the 1-Wire bus.
\r
232 * \param pin A bitmask of the bus to read from.
\r
234 * \return The byte read from the bus.
\r
236 unsigned char OWI_ReceiveByte(unsigned char pin)
\r
238 unsigned char data;
\r
241 // Clear the temporary input variable.
\r
244 // Do once for each bit
\r
245 for (i = 0; i < 8; i++) {
\r
246 // Shift temporary input variable right.
\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
260 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es).
\r
262 * \param pins A bitmask of the buses to send the SKIP ROM command to.
\r
264 void OWI_SkipRom(unsigned char pins)
\r
266 // Send the SKIP ROM command on the bus.
\r
267 OWI_SendByte(OWI_ROM_SKIP, pins);
\r
271 /*! \brief Sends the READ ROM command and reads back the ROM id.
\r
273 * \param romValue A pointer where the id will be placed.
\r
275 * \param pin A bitmask of the bus to read from.
\r
277 void OWI_ReadRom(unsigned char * romValue, unsigned char pin)
\r
279 unsigned char bytesLeft = 8;
\r
281 // Send the READ ROM command on the bus.
\r
282 OWI_SendByte(OWI_ROM_READ, pin);
\r
285 while (bytesLeft > 0) {
\r
286 // Place the received data in memory.
\r
287 *romValue++ = OWI_ReceiveByte(pin);
\r
293 /*! \brief Sends the MATCH ROM command and the ROM id to match against.
\r
295 * \param romValue A pointer to the ID to match against.
\r
297 * \param pins A bitmask of the buses to perform the MATCH ROM command on.
\r
299 void OWI_MatchRom(unsigned char * romValue, unsigned char pins)
\r
301 unsigned char bytesLeft = 8;
\r
303 // Send the MATCH ROM command.
\r
304 OWI_SendByte(OWI_ROM_MATCH, pins);
\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
315 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the
\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
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
331 * \param pin A bit-mask of the bus to perform a ROM search on.
\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
339 * \note See main.c for an example of how to utilize this function.
\r
341 unsigned char OWI_SearchRom(unsigned char * bitPattern,
\r
342 unsigned char lastDeviation, unsigned char pin)
\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
350 // Send SEARCH ROM command on the bus.
\r
351 OWI_SendByte(OWI_ROM_SEARCH, pin);
\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
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
367 (*bitPattern) |= bitMask;
\r
369 (*bitPattern) &= ~bitMask;
\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
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
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
391 // IF the bit is already 1, do nothing.
\r
396 // Send the selected bit to the bus.
\r
397 if ((*bitPattern) & bitMask) {
\r
398 OWI_WriteBit1(pin);
\r
400 OWI_WriteBit0(pin);
\r
403 // Increment current bit.
\r
406 // Adjust bitMask and bitPattern pointer.
\r
414 return newDeviation;
\r
418 /* Functions for handling CRC */
\r
419 /*! \brief Compute the CRC8 value of a data set.
\r
421 * This function will compute the CRC8 or DOW-CRC of inData using seed
\r
422 * as inital value for the CRC.
\r
424 * \param inData One byte of data to compute CRC from.
\r
426 * \param seed The starting value of the CRC.
\r
428 * \return The CRC8 of inData with seed as initial value.
\r
430 * \note Setting seed to 0 computes the crc8 of the inData.
\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
436 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)
\r
438 unsigned char bitsLeft;
\r
439 unsigned char temp;
\r
441 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {
\r
442 temp = ((seed ^ inData) & 0x01);
\r
458 /*! \brief Compute the CRC16 value of a data set.
\r
460 * This function will compute the CRC16 of inData using seed
\r
461 * as inital value for the CRC.
\r
463 * \param inData One byte of data to compute CRC from.
\r
465 * \param seed The starting value of the CRC.
\r
467 * \return The CRC16 of inData with seed as initial value.
\r
469 * \note Setting seed to 0 computes the crc16 of the inData.
\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
475 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)
\r
477 unsigned char bitsLeft;
\r
478 unsigned char temp;
\r
480 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {
\r
481 temp = ((seed ^ inData) & 0x01);
\r
498 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier.
\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
504 * \param *romValue A pointer to an array holding a 64 bit identifier.
\r
506 * \retval OWI_CRC_OK The CRC's matched.
\r
507 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match.
\r
509 unsigned char OWI_CheckRomCRC(unsigned char *romValue)
\r
512 unsigned char crc8 = 0;
\r
514 for (i = 0; i < 7; i++) {
\r
515 crc8 = OWI_ComputeCRC8(*romValue, crc8);
\r
519 if (crc8 == (*romValue)) {
\r
523 return OWI_CRC_ERROR;
\r