############################################################################### # # # IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:36 # # Copyright 1996-2007 IAR Systems. All rights reserved. # # # # Source file = C:\home\kevin\pub\src\bc100\IAR\OWI.c # # Command line = C:\home\kevin\pub\src\bc100\IAR\OWI.c # # --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # # 0\IAR\Release\Obj\ -D NDEBUG -lCN # # C:\home\kevin\pub\src\bc100\IAR\Release\List\ # # -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # # t\ --initializers_in_flash -s9 --no_cross_call # # --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # # "C:\Program Files\IAR Systems\Embedded # # Workbench 4.0\avr\INC\" -I "C:\Program # # Files\IAR Systems\Embedded Workbench # # 4.0\avr\INC\CLIB\" --eeprom_size 512 # # --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # # 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # # 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # # 112-126 # # Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # # 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # # 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # # Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # # 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # # 83-84,87-89,91,94-95,98,100,104-105,108-109, # # 112-115,118-126 # # Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # # 116-117 # # List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\OW # # I.lst # # Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI # # .r90 # # # # # ############################################################################### C:\home\kevin\pub\src\bc100\IAR\OWI.c 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ 2 /*! \file ******************************************************************** 3 * 4 * \brief 5 * Functions for 1-Wire(R) bus communication 6 * 7 * High level functions for transmission of full bytes on the 1-Wire(R) 8 * bus and implementations of ROM commands.\n 9 * Polled software only implementation of the basic bit-level signalling 10 * in the 1-Wire(R) protocol.\n 11 * Includes functions for computing and checking CRC8 & 16 values of data 12 * sets, and of 64 bit ROM identifiers. 13 * Supported devices: All AVRs. 14 * 15 * \par Application Note: 16 * AVR458: Charging Li-Ion Batteries with BC100\n 17 * AVR463: Charging NiMH Batteries with BC100\n 18 * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. 19 * 20 * \par Documentation: 21 * For comprehensive code documentation, supported compilers, compiler 22 * settings and supported devices see readme.html 23 * 24 * \author 25 * Atmel Corporation: http://www.atmel.com \n 26 * Support email: avr@atmel.com \n 27 * Original author: \n 28 * 29 * $Name$ 30 * $Revision: 2299 $ 31 * $RCSfile$ 32 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ 33 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n 34 ****************************************************************************/ 35 36 #include \ In segment ABSOLUTE, at 0x3b \ volatile __io _A_PORTA \ _A_PORTA: \ 00000000 DS 1 \ In segment ABSOLUTE, at 0x3a \ volatile __io _A_DDRA \ _A_DDRA: \ 00000000 DS 1 \ In segment ABSOLUTE, at 0x39 \ volatile __io _A_PINA \ _A_PINA: \ 00000000 DS 1 37 #include 38 39 #include "OWI.h" 40 41 42 //****************************************************************************** 43 // Functions 44 //****************************************************************************** 45 /*! \brief Initialization of the one wire bus(es). (Software only driver) 46 * 47 * This function initializes the 1-Wire bus(es) by releasing it and 48 * waiting until any presence signals are finished. 49 * 50 * \param pins A bitmask of the buses to initialize. 51 */ \ In segment CODE, align 2, keep-with-next 52 void OWI_Init(unsigned char pins){ \ OWI_Init: 53 OWI_RELEASE_BUS(pins); \ 00000000 9500 COM R16 \ 00000002 B31A IN R17, 0x1A \ 00000004 2310 AND R17, R16 \ 00000006 BB1A OUT 0x1A, R17 \ 00000008 B31B IN R17, 0x1B \ 0000000A 2310 AND R17, R16 \ 0000000C BB1B OUT 0x1B, R17 54 // The first rising edge can be interpreted by a slave as the end of a 55 // Reset-pulse. Delay for the required reset recovery time (H) to be 56 // sure that the real reset is interpreted correctly. 57 __delay_cycles(OWI_DELAY_H_STD_MODE); \ 0000000E EB0C LDI R16, 188 \ 00000010 E013 LDI R17, 3 \ 00000012 5001 SUBI R16, 1 \ 00000014 4010 SBCI R17, 0 \ 00000016 F7E9 BRNE $-4 \ 00000018 C000 RJMP $+2 58 } \ 0000001A 9508 RET \ 0000001C REQUIRE _A_PORTA \ 0000001C REQUIRE _A_DDRA 59 60 61 /*! \brief Write a '1' bit to the bus(es). (Software only driver) 62 * 63 * Generates the waveform for transmission of a '1' bit on the 1-Wire 64 * bus. 65 * 66 * \param pins A bitmask of the buses to write to. 67 */ \ In segment CODE, align 2, keep-with-next 68 void OWI_WriteBit1(unsigned char pins){ \ OWI_WriteBit1: 69 unsigned char intState; 70 71 // Disable interrupts. 72 intState = __save_interrupt(); \ 00000000 B71F IN R17, 0x3F 73 __disable_interrupt(); \ 00000002 94F8 CLI 74 75 // Drive bus low and delay. 76 OWI_PULL_BUS_LOW(pins); \ 00000004 B32A IN R18, 0x1A \ 00000006 2B20 OR R18, R16 \ 00000008 BB2A OUT 0x1A, R18 \ 0000000A 9500 COM R16 \ 0000000C B32B IN R18, 0x1B \ 0000000E 2320 AND R18, R16 \ 00000010 BB2B OUT 0x1B, R18 77 __delay_cycles(OWI_DELAY_A_STD_MODE); \ 00000012 E02B LDI R18, 11 \ 00000014 952A DEC R18 \ 00000016 F7F1 BRNE $-2 \ 00000018 C000 RJMP $+2 78 79 // Release bus and delay. 80 OWI_RELEASE_BUS(pins); \ 0000001A B32A IN R18, 0x1A \ 0000001C 2320 AND R18, R16 \ 0000001E BB2A OUT 0x1A, R18 \ 00000020 B32B IN R18, 0x1B \ 00000022 2320 AND R18, R16 \ 00000024 BB2B OUT 0x1B, R18 81 __delay_cycles(OWI_DELAY_B_STD_MODE); \ 00000026 EA06 LDI R16, 166 \ 00000028 950A DEC R16 \ 0000002A F7F1 BRNE $-2 \ 0000002C 0000 NOP 82 83 // Restore interrupts. 84 __restore_interrupt(intState); \ 0000002E BF1F OUT 0x3F, R17 85 } \ 00000030 9508 RET \ 00000032 REQUIRE _A_PORTA \ 00000032 REQUIRE _A_DDRA 86 87 /*! \brief Write a '0' to the bus(es). (Software only driver) 88 * 89 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) 90 * bus. 91 * 92 * \param pins A bitmask of the buses to write to. 93 */ \ In segment CODE, align 2, keep-with-next 94 void OWI_WriteBit0(unsigned char pins) \ OWI_WriteBit0: 95 { 96 unsigned char intState; 97 98 // Disable interrupts. 99 intState = __save_interrupt(); \ 00000000 B71F IN R17, 0x3F 100 __disable_interrupt(); \ 00000002 94F8 CLI 101 102 // Drive bus low and delay. 103 OWI_PULL_BUS_LOW(pins); \ 00000004 B32A IN R18, 0x1A \ 00000006 2B20 OR R18, R16 \ 00000008 BB2A OUT 0x1A, R18 \ 0000000A 9500 COM R16 \ 0000000C B32B IN R18, 0x1B \ 0000000E 2320 AND R18, R16 \ 00000010 BB2B OUT 0x1B, R18 104 __delay_cycles(OWI_DELAY_C_STD_MODE); \ 00000012 E92B LDI R18, 155 \ 00000014 952A DEC R18 \ 00000016 F7F1 BRNE $-2 \ 00000018 C000 RJMP $+2 105 106 // Release bus and delay. 107 OWI_RELEASE_BUS(pins); \ 0000001A B32A IN R18, 0x1A \ 0000001C 2320 AND R18, R16 \ 0000001E BB2A OUT 0x1A, R18 \ 00000020 B32B IN R18, 0x1B \ 00000022 2320 AND R18, R16 \ 00000024 BB2B OUT 0x1B, R18 108 __delay_cycles(OWI_DELAY_D_STD_MODE); \ 00000026 E106 LDI R16, 22 \ 00000028 950A DEC R16 \ 0000002A F7F1 BRNE $-2 \ 0000002C 0000 NOP 109 110 // Restore interrupts. 111 __restore_interrupt(intState); \ 0000002E BF1F OUT 0x3F, R17 112 } \ 00000030 9508 RET \ 00000032 REQUIRE _A_PORTA \ 00000032 REQUIRE _A_DDRA 113 114 /*! \brief Read a bit from the bus(es). (Software only driver) 115 * 116 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). 117 * 118 * \param pins A bitmask of the bus(es) to read from. 119 * 120 * \return A bitmask of the buses where a '1' was read. 121 */ \ In segment CODE, align 2, keep-with-next 122 unsigned char OWI_ReadBit(unsigned char pins) \ OWI_ReadBit: 123 { 124 unsigned char intState; 125 unsigned char bitsRead; 126 127 // Disable interrupts. 128 intState = __save_interrupt(); \ 00000000 B72F IN R18, 0x3F 129 __disable_interrupt(); \ 00000002 94F8 CLI 130 131 // Drive bus low and delay. 132 OWI_PULL_BUS_LOW(pins); \ 00000004 B31A IN R17, 0x1A \ 00000006 2B10 OR R17, R16 \ 00000008 BB1A OUT 0x1A, R17 \ 0000000A 2F10 MOV R17, R16 \ 0000000C 9510 COM R17 \ 0000000E B33B IN R19, 0x1B \ 00000010 2331 AND R19, R17 \ 00000012 BB3B OUT 0x1B, R19 133 __delay_cycles(OWI_DELAY_A_STD_MODE); \ 00000014 E03B LDI R19, 11 \ 00000016 953A DEC R19 \ 00000018 F7F1 BRNE $-2 \ 0000001A C000 RJMP $+2 134 135 // Release bus and delay. 136 OWI_RELEASE_BUS(pins); \ 0000001C B33A IN R19, 0x1A \ 0000001E 2331 AND R19, R17 \ 00000020 BB3A OUT 0x1A, R19 \ 00000022 B33B IN R19, 0x1B \ 00000024 2331 AND R19, R17 \ 00000026 BB3B OUT 0x1B, R19 137 __delay_cycles(OWI_DELAY_E_STD_MODE); \ 00000028 E113 LDI R17, 19 \ 0000002A 951A DEC R17 \ 0000002C F7F1 BRNE $-2 \ 0000002E C000 RJMP $+2 138 139 // Sample bus and delay. 140 bitsRead = OWI_PIN & pins; \ 00000030 B319 IN R17, 0x19 \ 00000032 2310 AND R17, R16 141 __delay_cycles(OWI_DELAY_F_STD_MODE); \ 00000034 E80E LDI R16, 142 \ 00000036 950A DEC R16 \ 00000038 F7F1 BRNE $-2 \ 0000003A 0000 NOP 142 143 // Restore interrupts. 144 __restore_interrupt(intState); \ 0000003C BF2F OUT 0x3F, R18 145 146 return bitsRead; \ 0000003E 2F01 MOV R16, R17 \ 00000040 9508 RET \ 00000042 REQUIRE _A_PORTA \ 00000042 REQUIRE _A_DDRA \ 00000042 REQUIRE _A_PINA 147 } 148 149 150 /*! \brief Send a Reset signal and listen for Presence signal. (software 151 * only driver) 152 * 153 * Generates the waveform for transmission of a Reset pulse on the 154 * 1-Wire(R) bus and listens for presence signals. 155 * 156 * \param pins A bitmask of the buses to send the Reset signal on. 157 * 158 * \return A bitmask of the buses where a presence signal was detected. 159 */ \ In segment CODE, align 2, keep-with-next 160 unsigned char OWI_DetectPresence(unsigned char pins) \ OWI_DetectPresence: 161 { 162 unsigned char intState; 163 unsigned char presenceDetected; 164 165 // Disable interrupts. 166 intState = __save_interrupt(); \ 00000000 B72F IN R18, 0x3F 167 __disable_interrupt(); \ 00000002 94F8 CLI 168 169 // Drive bus low and delay. 170 OWI_PULL_BUS_LOW(pins); \ 00000004 B31A IN R17, 0x1A \ 00000006 2B10 OR R17, R16 \ 00000008 BB1A OUT 0x1A, R17 \ 0000000A 2F10 MOV R17, R16 \ 0000000C 9510 COM R17 \ 0000000E B33B IN R19, 0x1B \ 00000010 2331 AND R19, R17 \ 00000012 BB3B OUT 0x1B, R19 171 __delay_cycles(OWI_DELAY_H_STD_MODE); \ 00000014 EB4C LDI R20, 188 \ 00000016 E053 LDI R21, 3 \ 00000018 5041 SUBI R20, 1 \ 0000001A 4050 SBCI R21, 0 \ 0000001C F7E9 BRNE $-4 \ 0000001E C000 RJMP $+2 172 173 // Release bus and delay. 174 OWI_RELEASE_BUS(pins); \ 00000020 B33A IN R19, 0x1A \ 00000022 2331 AND R19, R17 \ 00000024 BB3A OUT 0x1A, R19 \ 00000026 B33B IN R19, 0x1B \ 00000028 2331 AND R19, R17 \ 0000002A BB3B OUT 0x1B, R19 175 __delay_cycles(OWI_DELAY_I_STD_MODE); \ 0000002C EB16 LDI R17, 182 \ 0000002E 951A DEC R17 \ 00000030 F7F1 BRNE $-2 \ 00000032 0000 NOP 176 177 // Sample bus to detect presence signal and delay. 178 presenceDetected = ((~OWI_PIN) & pins); \ 00000034 B319 IN R17, 0x19 \ 00000036 9510 COM R17 \ 00000038 2301 AND R16, R17 179 __delay_cycles(OWI_DELAY_J_STD_MODE); \ 0000003A E340 LDI R20, 48 \ 0000003C E053 LDI R21, 3 \ 0000003E 5041 SUBI R20, 1 \ 00000040 4050 SBCI R21, 0 \ 00000042 F7E9 BRNE $-4 \ 00000044 C000 RJMP $+2 180 181 // Restore interrupts. 182 __restore_interrupt(intState); \ 00000046 BF2F OUT 0x3F, R18 183 184 return presenceDetected; \ 00000048 9508 RET \ 0000004A REQUIRE _A_PORTA \ 0000004A REQUIRE _A_DDRA \ 0000004A REQUIRE _A_PINA 185 } 186 187 188 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es). 189 * 190 * This function automates the task of sending a complete byte 191 * of data on the 1-Wire bus(es). 192 * 193 * \param data The data to send on the bus(es). 194 * 195 * \param pins A bitmask of the buses to send the data to. 196 */ \ In segment CODE, align 2, keep-with-next 197 void OWI_SendByte(unsigned char data, unsigned char pins) \ OWI_SendByte: 198 { \ 00000000 93AA ST -Y, R26 \ 00000002 939A ST -Y, R25 \ 00000004 938A ST -Y, R24 \ 00000006 2FA0 MOV R26, R16 \ 00000008 2F91 MOV R25, R17 199 unsigned char temp; 200 unsigned char i; 201 202 // Do once for each bit 203 for (i = 0; i < 8; i++) { \ 0000000A E088 LDI R24, 8 204 // Determine if LSB is '0' or '1' and transmit corresponding 205 // waveform on the bus. 206 temp = data & 0x01; 207 208 if (temp) { \ ??OWI_SendByte_0: \ 0000000C FBA0 BST R26, 0 \ 0000000E 2F09 MOV R16, R25 \ 00000010 F416 BRTC ??OWI_SendByte_1 209 OWI_WriteBit1(pins); \ 00000012 .... RCALL OWI_WriteBit1 \ 00000014 C001 RJMP ??OWI_SendByte_2 210 } else { 211 OWI_WriteBit0(pins); \ ??OWI_SendByte_1: \ 00000016 .... RCALL OWI_WriteBit0 212 } 213 214 data >>= 1; // Right shift the data to get next bit. \ ??OWI_SendByte_2: \ 00000018 95A6 LSR R26 215 } \ 0000001A 958A DEC R24 \ 0000001C F7B9 BRNE ??OWI_SendByte_0 216 } \ 0000001E 9189 LD R24, Y+ \ 00000020 9199 LD R25, Y+ \ 00000022 91A9 LD R26, Y+ \ 00000024 9508 RET 217 218 219 /*! \brief Receives one byte of data from the 1-Wire(R) bus. 220 * 221 * This function automates the task of receiving a complete byte 222 * of data from the 1-Wire bus. 223 * 224 * \param pin A bitmask of the bus to read from. 225 * 226 * \return The byte read from the bus. 227 */ \ In segment CODE, align 2, keep-with-next 228 unsigned char OWI_ReceiveByte(unsigned char pin) \ OWI_ReceiveByte: 229 { \ 00000000 93AA ST -Y, R26 \ 00000002 939A ST -Y, R25 \ 00000004 938A ST -Y, R24 \ 00000006 2FA0 MOV R26, R16 230 unsigned char data; 231 unsigned char i; 232 233 // Clear the temporary input variable. 234 data = 0x00; \ 00000008 E090 LDI R25, 0 235 236 // Do once for each bit 237 for (i = 0; i < 8; i++) { \ 0000000A E088 LDI R24, 8 238 // Shift temporary input variable right. 239 data >>= 1; \ ??OWI_ReceiveByte_0: \ 0000000C 9596 LSR R25 240 241 // Set the MSB if a '1' value is read from the bus. 242 // Leave as it is ('0') else. 243 if (OWI_ReadBit(pin)) { \ 0000000E 2F0A MOV R16, R26 \ 00000010 .... RCALL OWI_ReadBit \ 00000012 2300 TST R16 \ 00000014 F009 BREQ ??OWI_ReceiveByte_1 244 data |= 0x80; \ 00000016 6890 ORI R25, 0x80 245 } 246 } \ ??OWI_ReceiveByte_1: \ 00000018 958A DEC R24 \ 0000001A F7C1 BRNE ??OWI_ReceiveByte_0 247 248 return data; \ 0000001C 2F09 MOV R16, R25 \ 0000001E 9189 LD R24, Y+ \ 00000020 9199 LD R25, Y+ \ 00000022 91A9 LD R26, Y+ \ 00000024 9508 RET 249 } 250 251 252 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). 253 * 254 * \param pins A bitmask of the buses to send the SKIP ROM command to. 255 */ \ In segment CODE, align 2, keep-with-next 256 void OWI_SkipRom(unsigned char pins) \ OWI_SkipRom: 257 { 258 // Send the SKIP ROM command on the bus. 259 OWI_SendByte(OWI_ROM_SKIP, pins); \ 00000000 2F10 MOV R17, R16 \ 00000002 EC0C LDI R16, 204 \ 00000004 .... RJMP OWI_SendByte 260 } 261 262 263 /*! \brief Sends the READ ROM command and reads back the ROM id. 264 * 265 * \param romValue A pointer where the id will be placed. 266 * 267 * \param pin A bitmask of the bus to read from. 268 */ \ In segment CODE, align 2, keep-with-next 269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin) \ OWI_ReadRom: 270 { \ 00000000 93BA ST -Y, R27 \ 00000002 93AA ST -Y, R26 \ 00000004 939A ST -Y, R25 \ 00000006 938A ST -Y, R24 \ 00000008 01D8 MOVW R27:R26, R17:R16 \ 0000000A 2F92 MOV R25, R18 271 unsigned char bytesLeft = 8; 272 273 // Send the READ ROM command on the bus. 274 OWI_SendByte(OWI_ROM_READ, pin); \ 0000000C 2F12 MOV R17, R18 \ 0000000E E303 LDI R16, 51 \ 00000010 .... RCALL OWI_SendByte \ 00000012 E088 LDI R24, 8 275 276 // Do 8 times. 277 while (bytesLeft > 0) { 278 // Place the received data in memory. 279 *romValue++ = OWI_ReceiveByte(pin); \ ??OWI_ReadRom_0: \ 00000014 2F09 MOV R16, R25 \ 00000016 .... RCALL OWI_ReceiveByte \ 00000018 930D ST X+, R16 280 bytesLeft--; \ 0000001A 958A DEC R24 281 } \ 0000001C F7D9 BRNE ??OWI_ReadRom_0 282 } \ 0000001E REQUIRE ?Subroutine0 \ 0000001E ; // Fall through to label ?Subroutine0 \ In segment CODE, align 2, keep-with-next \ ?Subroutine0: \ 00000000 9189 LD R24, Y+ \ 00000002 9199 LD R25, Y+ \ 00000004 91A9 LD R26, Y+ \ 00000006 91B9 LD R27, Y+ \ 00000008 9508 RET 283 284 285 /*! \brief Sends the MATCH ROM command and the ROM id to match against. 286 * 287 * \param romValue A pointer to the ID to match against. 288 * 289 * \param pins A bitmask of the buses to perform the MATCH ROM command on. 290 */ \ In segment CODE, align 2, keep-with-next 291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins) \ OWI_MatchRom: 292 { \ 00000000 93BA ST -Y, R27 \ 00000002 93AA ST -Y, R26 \ 00000004 939A ST -Y, R25 \ 00000006 938A ST -Y, R24 \ 00000008 01D8 MOVW R27:R26, R17:R16 \ 0000000A 2F92 MOV R25, R18 293 unsigned char bytesLeft = 8; 294 295 // Send the MATCH ROM command. 296 OWI_SendByte(OWI_ROM_MATCH, pins); \ 0000000C 2F12 MOV R17, R18 \ 0000000E E505 LDI R16, 85 \ 00000010 .... RCALL OWI_SendByte \ 00000012 E088 LDI R24, 8 297 298 // Do once for each byte. 299 while (bytesLeft > 0) { 300 // Transmit 1 byte of the ID to match. 301 OWI_SendByte(*romValue++, pins); \ ??OWI_MatchRom_0: \ 00000014 2F19 MOV R17, R25 \ 00000016 910D LD R16, X+ \ 00000018 .... RCALL OWI_SendByte 302 bytesLeft--; \ 0000001A 958A DEC R24 303 } \ 0000001C F7D9 BRNE ??OWI_MatchRom_0 304 } \ 0000001E .... RJMP ?Subroutine0 305 306 307 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the 308 * 1-Wire(R) bus. 309 * 310 * \param bitPattern A pointer to an 8 byte char array where the 311 * discovered identifier will be placed. When 312 * searching for several slaves, a copy of the 313 * last found identifier should be supplied in 314 * the array, or the search will fail. 315 * 316 * \param lastDeviation The bit position where the algorithm made a 317 * choice the last time it was run. This argument 318 * should be 0 when a search is initiated. Supplying 319 * the return argument of this function when calling 320 * repeatedly will go through the complete slave 321 * search. 322 * 323 * \param pin A bit-mask of the bus to perform a ROM search on. 324 * 325 * \return The last bit position where there was a discrepancy between slave 326 * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED 327 * if an error was detected (e.g. a device was connected to the bus during the 328 * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be 329 * discovered. 330 * 331 * \note See main.c for an example of how to utilize this function. 332 */ \ In segment CODE, align 2, keep-with-next 333 unsigned char OWI_SearchRom(unsigned char * bitPattern, \ OWI_SearchRom: 334 unsigned char lastDeviation, unsigned char pin) 335 { \ 00000000 927A ST -Y, R7 \ 00000002 926A ST -Y, R6 \ 00000004 925A ST -Y, R5 \ 00000006 924A ST -Y, R4 \ 00000008 93BA ST -Y, R27 \ 0000000A 93AA ST -Y, R26 \ 0000000C 939A ST -Y, R25 \ 0000000E 938A ST -Y, R24 \ 00000010 REQUIRE ?Register_R4_is_cg_reg \ 00000010 REQUIRE ?Register_R5_is_cg_reg \ 00000010 REQUIRE ?Register_R6_is_cg_reg \ 00000010 REQUIRE ?Register_R7_is_cg_reg \ 00000010 01D8 MOVW R27:R26, R17:R16 \ 00000012 2E62 MOV R6, R18 \ 00000014 2E43 MOV R4, R19 336 unsigned char currentBit = 1; \ 00000016 E081 LDI R24, 1 337 unsigned char newDeviation = 0; \ 00000018 2455 CLR R5 338 unsigned char bitMask = 0x01; \ 0000001A E091 LDI R25, 1 339 unsigned char bitA; 340 unsigned char bitB; 341 342 // Send SEARCH ROM command on the bus. 343 OWI_SendByte(OWI_ROM_SEARCH, pin); \ 0000001C 2F13 MOV R17, R19 \ 0000001E EF00 LDI R16, 240 \ 00000020 .... RCALL OWI_SendByte 344 345 // Walk through all 64 bits. 346 while (currentBit <= 64) { 347 // Read bit from bus twice. 348 bitA = OWI_ReadBit(pin); \ ??OWI_SearchRom_0: \ 00000022 2D04 MOV R16, R4 \ 00000024 .... RCALL OWI_ReadBit \ 00000026 2E70 MOV R7, R16 349 bitB = OWI_ReadBit(pin); \ 00000028 2D04 MOV R16, R4 \ 0000002A .... RCALL OWI_ReadBit 350 351 if (bitA && bitB) { \ 0000002C 2077 TST R7 \ 0000002E F021 BREQ ??OWI_SearchRom_1 \ 00000030 2300 TST R16 \ 00000032 F011 BREQ ??OWI_SearchRom_1 352 // Both bits 1 (Error). 353 newDeviation = OWI_ROM_SEARCH_FAILED; 354 return newDeviation; \ 00000034 EF0F LDI R16, 255 \ 00000036 C02C RJMP ??OWI_SearchRom_2 355 } else if (bitA ^ bitB) { \ ??OWI_SearchRom_1: \ 00000038 2507 EOR R16, R7 \ 0000003A F069 BREQ ??OWI_SearchRom_3 356 // Bits A and B are different. All devices have the same bit here. 357 // Set the bit in bitPattern to this value. 358 if (bitA) { \ 0000003C 2077 TST R7 \ 0000003E F029 BREQ ??OWI_SearchRom_4 359 (*bitPattern) |= bitMask; \ ??OWI_SearchRom_5: \ 00000040 01FD MOVW R31:R30, R27:R26 \ 00000042 8100 LD R16, Z \ 00000044 2B09 OR R16, R25 \ 00000046 8300 ST Z, R16 \ 00000048 C014 RJMP ??OWI_SearchRom_6 360 } else { 361 (*bitPattern) &= ~bitMask; \ ??OWI_SearchRom_4: \ 0000004A 2F09 MOV R16, R25 \ 0000004C 9500 COM R16 \ 0000004E 911C LD R17, X \ 00000050 2310 AND R17, R16 \ 00000052 931C ST X, R17 \ 00000054 C00E RJMP ??OWI_SearchRom_6 362 } 363 } else { 364 // If this is where a choice was made the last time, 365 // a '1' bit is selected this time. 366 if (currentBit == lastDeviation) { \ ??OWI_SearchRom_3: \ 00000056 1586 CP R24, R6 \ 00000058 F399 BREQ ??OWI_SearchRom_5 367 (*bitPattern) |= bitMask; 368 } 369 370 // For the rest of the id, '0' bits are selected when 371 // discrepancies occur. 372 else if (currentBit > lastDeviation) { \ 0000005A 1668 CP R6, R24 \ 0000005C F430 BRCC ??OWI_SearchRom_7 373 (*bitPattern) &= ~bitMask; \ 0000005E 2F09 MOV R16, R25 \ 00000060 9500 COM R16 \ 00000062 911C LD R17, X \ 00000064 2310 AND R17, R16 \ 00000066 931C ST X, R17 374 newDeviation = currentBit; \ 00000068 C003 RJMP ??OWI_SearchRom_8 375 } 376 377 // If current bit in bit pattern = 0, then this is 378 // out new deviation. 379 else if ( !(*bitPattern & bitMask)) { \ ??OWI_SearchRom_7: \ 0000006A 910C LD R16, X \ 0000006C 2309 AND R16, R25 \ 0000006E F409 BRNE ??OWI_SearchRom_6 380 newDeviation = currentBit; \ ??OWI_SearchRom_8: \ 00000070 2E58 MOV R5, R24 381 } 382 383 // IF the bit is already 1, do nothing. 384 else { 385 } 386 } 387 388 // Send the selected bit to the bus. 389 if ((*bitPattern) & bitMask) { \ ??OWI_SearchRom_6: \ 00000072 910C LD R16, X \ 00000074 2309 AND R16, R25 \ 00000076 2D04 MOV R16, R4 \ 00000078 F011 BREQ ??OWI_SearchRom_9 390 OWI_WriteBit1(pin); \ 0000007A .... RCALL OWI_WriteBit1 \ 0000007C C001 RJMP ??OWI_SearchRom_10 391 } else { 392 OWI_WriteBit0(pin); \ ??OWI_SearchRom_9: \ 0000007E .... RCALL OWI_WriteBit0 393 } 394 395 // Increment current bit. 396 currentBit++; \ ??OWI_SearchRom_10: \ 00000080 9583 INC R24 397 398 // Adjust bitMask and bitPattern pointer. 399 bitMask <<= 1; \ 00000082 0F99 LSL R25 400 if (!bitMask) { \ 00000084 F411 BRNE ??OWI_SearchRom_11 401 bitMask = 0x01; \ 00000086 E091 LDI R25, 1 402 bitPattern++; \ 00000088 9611 ADIW R27:R26, 1 403 } 404 } \ ??OWI_SearchRom_11: \ 0000008A 3481 CPI R24, 65 \ 0000008C F250 BRCS ??OWI_SearchRom_0 405 406 return newDeviation; \ 0000008E 2D05 MOV R16, R5 \ ??OWI_SearchRom_2: \ 00000090 9189 LD R24, Y+ \ 00000092 9199 LD R25, Y+ \ 00000094 91A9 LD R26, Y+ \ 00000096 91B9 LD R27, Y+ \ 00000098 9049 LD R4, Y+ \ 0000009A 9059 LD R5, Y+ \ 0000009C 9069 LD R6, Y+ \ 0000009E 9079 LD R7, Y+ \ 000000A0 9508 RET 407 } 408 409 410 /* Functions for handling CRC */ 411 /*! \brief Compute the CRC8 value of a data set. 412 * 413 * This function will compute the CRC8 or DOW-CRC of inData using seed 414 * as inital value for the CRC. 415 * 416 * \param inData One byte of data to compute CRC from. 417 * 418 * \param seed The starting value of the CRC. 419 * 420 * \return The CRC8 of inData with seed as initial value. 421 * 422 * \note Setting seed to 0 computes the crc8 of the inData. 423 * 424 * \note Constantly passing the return value of this function 425 * As the seed argument computes the CRC8 value of a 426 * longer string of data. 427 */ \ In segment CODE, align 2, keep-with-next 428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) \ OWI_ComputeCRC8: 429 { 430 unsigned char bitsLeft; 431 unsigned char temp; 432 433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { \ 00000000 E038 LDI R19, 8 434 temp = ((seed ^ inData) & 0x01); 435 436 if (temp == 0) { \ ??OWI_ComputeCRC8_0: \ 00000002 2F21 MOV R18, R17 \ 00000004 7021 ANDI R18, 0x01 \ 00000006 2F40 MOV R20, R16 \ 00000008 7041 ANDI R20, 0x01 \ 0000000A 2742 EOR R20, R18 \ 0000000C F411 BRNE ??OWI_ComputeCRC8_1 437 seed >>= 1; \ 0000000E 9516 LSR R17 \ 00000010 C004 RJMP ??OWI_ComputeCRC8_2 438 } else { 439 seed ^= 0x18; 440 seed >>= 1; 441 seed |= 0x80; \ ??OWI_ComputeCRC8_1: \ 00000012 E128 LDI R18, 24 \ 00000014 2712 EOR R17, R18 \ 00000016 9516 LSR R17 \ 00000018 6810 ORI R17, 0x80 442 } 443 444 inData >>= 1; \ ??OWI_ComputeCRC8_2: \ 0000001A 9506 LSR R16 445 } \ 0000001C 953A DEC R19 \ 0000001E F789 BRNE ??OWI_ComputeCRC8_0 446 return seed; \ 00000020 2F01 MOV R16, R17 \ 00000022 9508 RET 447 } 448 449 450 /*! \brief Compute the CRC16 value of a data set. 451 * 452 * This function will compute the CRC16 of inData using seed 453 * as inital value for the CRC. 454 * 455 * \param inData One byte of data to compute CRC from. 456 * 457 * \param seed The starting value of the CRC. 458 * 459 * \return The CRC16 of inData with seed as initial value. 460 * 461 * \note Setting seed to 0 computes the crc16 of the inData. 462 * 463 * \note Constantly passing the return value of this function 464 * As the seed argument computes the CRC16 value of a 465 * longer string of data. 466 */ \ In segment CODE, align 2, keep-with-next 467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) \ OWI_ComputeCRC16: 468 { 469 unsigned char bitsLeft; 470 unsigned char temp; 471 472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { \ 00000000 E018 LDI R17, 8 473 temp = ((seed ^ inData) & 0x01); 474 475 if (temp == 0) { \ ??OWI_ComputeCRC16_0: \ 00000002 2F42 MOV R20, R18 \ 00000004 7041 ANDI R20, 0x01 \ 00000006 2F50 MOV R21, R16 \ 00000008 7051 ANDI R21, 0x01 \ 0000000A 2754 EOR R21, R20 \ 0000000C F419 BRNE ??OWI_ComputeCRC16_1 476 seed >>= 1; \ 0000000E 9536 LSR R19 \ 00000010 9527 ROR R18 \ 00000012 C008 RJMP ??OWI_ComputeCRC16_2 477 } else { 478 seed ^= 0x4002; 479 seed >>= 1; 480 seed |= 0x8000; \ ??OWI_ComputeCRC16_1: \ 00000014 E042 LDI R20, 2 \ 00000016 E450 LDI R21, 64 \ 00000018 2742 EOR R20, R18 \ 0000001A 2753 EOR R21, R19 \ 0000001C 019A MOVW R19:R18, R21:R20 \ 0000001E 9536 LSR R19 \ 00000020 9527 ROR R18 \ 00000022 6830 ORI R19, 0x80 481 } 482 483 inData >>= 1; \ ??OWI_ComputeCRC16_2: \ 00000024 9506 LSR R16 484 } \ 00000026 951A DEC R17 \ 00000028 F761 BRNE ??OWI_ComputeCRC16_0 485 486 return seed; \ 0000002A 0189 MOVW R17:R16, R19:R18 \ 0000002C 9508 RET 487 } 488 489 490 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier. 491 * 492 * This function computes the CRC8 value of the first 56 bits of a 493 * 64 bit identifier. It then checks the calculated value against the 494 * CRC value stored in ROM. 495 * 496 * \param *romValue A pointer to an array holding a 64 bit identifier. 497 * 498 * \retval OWI_CRC_OK The CRC's matched. 499 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. 500 */ \ In segment CODE, align 2, keep-with-next 501 unsigned char OWI_CheckRomCRC(unsigned char *romValue) \ OWI_CheckRomCRC: 502 { \ 00000000 93BA ST -Y, R27 \ 00000002 93AA ST -Y, R26 \ 00000004 938A ST -Y, R24 \ 00000006 01D8 MOVW R27:R26, R17:R16 503 unsigned char i; 504 unsigned char crc8 = 0; \ 00000008 E010 LDI R17, 0 505 506 for (i = 0; i < 7; i++) { \ 0000000A E087 LDI R24, 7 507 crc8 = OWI_ComputeCRC8(*romValue, crc8); \ ??OWI_CheckRomCRC_0: \ 0000000C 910D LD R16, X+ \ 0000000E .... RCALL OWI_ComputeCRC8 \ 00000010 2F10 MOV R17, R16 508 romValue++; 509 } \ 00000012 958A DEC R24 \ 00000014 F7D9 BRNE ??OWI_CheckRomCRC_0 510 511 if (crc8 == (*romValue)) { \ 00000016 910C LD R16, X \ 00000018 1710 CP R17, R16 \ 0000001A F411 BRNE ??OWI_CheckRomCRC_1 512 return OWI_CRC_OK; \ 0000001C E000 LDI R16, 0 \ 0000001E C001 RJMP ??OWI_CheckRomCRC_2 513 } 514 515 return OWI_CRC_ERROR; \ ??OWI_CheckRomCRC_1: \ 00000020 E001 LDI R16, 1 \ ??OWI_CheckRomCRC_2: \ 00000022 9189 LD R24, Y+ \ 00000024 91A9 LD R26, Y+ \ 00000026 91B9 LD R27, Y+ \ 00000028 9508 RET 516 } Maximum stack usage in bytes: Function CSTACK RSTACK -------- ------ ------ OWI_CheckRomCRC 3 2 -> OWI_ComputeCRC8 3 2 OWI_ComputeCRC16 0 2 OWI_ComputeCRC8 0 2 OWI_DetectPresence 0 2 OWI_Init 0 2 OWI_MatchRom 4 2 -> OWI_SendByte 4 2 -> OWI_SendByte 4 2 OWI_ReadBit 0 2 OWI_ReadRom 4 2 -> OWI_SendByte 4 2 -> OWI_ReceiveByte 4 2 OWI_ReceiveByte 3 2 -> OWI_ReadBit 3 2 OWI_SearchRom 8 2 -> OWI_SendByte 8 2 -> OWI_ReadBit 8 2 -> OWI_ReadBit 8 2 -> OWI_WriteBit1 8 2 -> OWI_WriteBit0 8 2 OWI_SendByte 3 2 -> OWI_WriteBit1 3 2 -> OWI_WriteBit0 3 2 OWI_SkipRom 0 2 -> OWI_SendByte 0 2 OWI_WriteBit0 0 2 OWI_WriteBit1 0 2 Segment part sizes: Function/Label Bytes -------------- ----- _A_PORTA 1 _A_DDRA 1 _A_PINA 1 OWI_Init 28 OWI_WriteBit1 50 OWI_WriteBit0 50 OWI_ReadBit 66 OWI_DetectPresence 74 OWI_SendByte 38 OWI_ReceiveByte 38 OWI_SkipRom 6 OWI_ReadRom 30 ?Subroutine0 10 OWI_MatchRom 32 OWI_SearchRom 162 OWI_ComputeCRC8 36 OWI_ComputeCRC16 46 OWI_CheckRomCRC 42 3 bytes in segment ABSOLUTE 708 bytes in segment CODE 708 bytes of CODE memory 0 bytes of DATA memory (+ 3 bytes shared) Errors: none Warnings: none