/////////////////////////////////////////////////////////////////////////////// // / // IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 / // Copyright 1996-2007 IAR Systems. All rights reserved. / // / // Source file = C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c / // Command line = C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c / // --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / // R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / // bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / // \List\ --initializers_in_flash -z2 --no_cse / // --no_inline --no_code_motion --no_cross_call / // --no_clustering --no_tbaa --debug / // -DENABLE_BIT_DEFINITIONS -e --require_prototypes -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 / // List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\OWI.s90 / // / // / /////////////////////////////////////////////////////////////////////////////// NAME OWI RSEG CSTACK:DATA:NOROOT(0) RSEG RSTACK:DATA:NOROOT(0) EXTERN ?EPILOGUE_B3_L09 EXTERN ?EPILOGUE_B4_L09 EXTERN ?EPILOGUE_B9_L09 EXTERN ?PROLOGUE3_L09 EXTERN ?PROLOGUE4_L09 EXTERN ?PROLOGUE9_L09 EXTERN ?Register_R4_is_cg_reg EXTERN ?Register_R5_is_cg_reg EXTERN ?Register_R6_is_cg_reg EXTERN ?Register_R7_is_cg_reg EXTERN ?Register_R8_is_cg_reg PUBLIC OWI_CheckRomCRC PUBLIC OWI_ComputeCRC16 PUBLIC OWI_ComputeCRC8 PUBLIC OWI_DetectPresence PUBLIC OWI_Init PUBLIC OWI_MatchRom PUBLIC OWI_ReadBit PUBLIC OWI_ReadRom PUBLIC OWI_ReceiveByte PUBLIC OWI_SearchRom PUBLIC OWI_SendByte PUBLIC OWI_SkipRom PUBLIC OWI_WriteBit0 PUBLIC OWI_WriteBit1 PUBWEAK _A_DDRA PUBWEAK _A_PINA PUBWEAK _A_PORTA PUBWEAK __?EEARH PUBWEAK __?EEARL PUBWEAK __?EECR PUBWEAK __?EEDR // C:\home\kevin\pub\src\bc100_cal\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 ASEGN ABSOLUTE:DATA:NOROOT,03bH // volatile __io _A_PORTA _A_PORTA: DS 1 ASEGN ABSOLUTE:DATA:NOROOT,03aH // volatile __io _A_DDRA _A_DDRA: DS 1 ASEGN ABSOLUTE:DATA:NOROOT,039H // volatile __io _A_PINA _A_PINA: 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 */ RSEG CODE:CODE:NOROOT(1) // 52 void OWI_Init(unsigned char pins){ OWI_Init: // 53 OWI_RELEASE_BUS(pins); MOV R17, R16 COM R17 IN R18, 0x1A AND R18, R17 OUT 0x1A, R18 MOV R17, R16 COM R17 IN R18, 0x1B AND R18, R17 OUT 0x1B, R18 // 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); LDI R18, 188 LDI R19, 3 SUBI R18, 1 SBCI R19, 0 BRNE $-4 RJMP $+2 // 58 } RET REQUIRE _A_PORTA 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 */ RSEG CODE:CODE:NOROOT(1) // 68 void OWI_WriteBit1(unsigned char pins){ OWI_WriteBit1: // 69 unsigned char intState; // 70 // 71 // Disable interrupts. // 72 intState = __save_interrupt(); IN R18, 0x3F MOV R17, R18 // 73 __disable_interrupt(); CLI // 74 // 75 // Drive bus low and delay. // 76 OWI_PULL_BUS_LOW(pins); IN R18, 0x1A OR R18, R16 OUT 0x1A, R18 MOV R18, R16 COM R18 IN R19, 0x1B AND R19, R18 OUT 0x1B, R19 // 77 __delay_cycles(OWI_DELAY_A_STD_MODE); LDI R18, 11 DEC R18 BRNE $-2 RJMP $+2 // 78 // 79 // Release bus and delay. // 80 OWI_RELEASE_BUS(pins); MOV R18, R16 COM R18 IN R19, 0x1A AND R19, R18 OUT 0x1A, R19 MOV R18, R16 COM R18 IN R19, 0x1B AND R19, R18 OUT 0x1B, R19 // 81 __delay_cycles(OWI_DELAY_B_STD_MODE); LDI R18, 166 DEC R18 BRNE $-2 NOP // 82 // 83 // Restore interrupts. // 84 __restore_interrupt(intState); OUT 0x3F, R17 // 85 } RET REQUIRE _A_PORTA 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 */ RSEG CODE:CODE:NOROOT(1) // 94 void OWI_WriteBit0(unsigned char pins) OWI_WriteBit0: // 95 { // 96 unsigned char intState; // 97 // 98 // Disable interrupts. // 99 intState = __save_interrupt(); IN R18, 0x3F MOV R17, R18 // 100 __disable_interrupt(); CLI // 101 // 102 // Drive bus low and delay. // 103 OWI_PULL_BUS_LOW(pins); IN R18, 0x1A OR R18, R16 OUT 0x1A, R18 MOV R18, R16 COM R18 IN R19, 0x1B AND R19, R18 OUT 0x1B, R19 // 104 __delay_cycles(OWI_DELAY_C_STD_MODE); LDI R18, 155 DEC R18 BRNE $-2 RJMP $+2 // 105 // 106 // Release bus and delay. // 107 OWI_RELEASE_BUS(pins); MOV R18, R16 COM R18 IN R19, 0x1A AND R19, R18 OUT 0x1A, R19 MOV R18, R16 COM R18 IN R19, 0x1B AND R19, R18 OUT 0x1B, R19 // 108 __delay_cycles(OWI_DELAY_D_STD_MODE); LDI R18, 22 DEC R18 BRNE $-2 NOP // 109 // 110 // Restore interrupts. // 111 __restore_interrupt(intState); OUT 0x3F, R17 // 112 } RET REQUIRE _A_PORTA 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 */ RSEG CODE:CODE:NOROOT(1) // 122 unsigned char OWI_ReadBit(unsigned char pins) OWI_ReadBit: // 123 { MOV R17, R16 // 124 unsigned char intState; // 125 unsigned char bitsRead; // 126 // 127 // Disable interrupts. // 128 intState = __save_interrupt(); IN R19, 0x3F MOV R18, R19 // 129 __disable_interrupt(); CLI // 130 // 131 // Drive bus low and delay. // 132 OWI_PULL_BUS_LOW(pins); IN R19, 0x1A OR R19, R17 OUT 0x1A, R19 MOV R19, R17 COM R19 IN R20, 0x1B AND R20, R19 OUT 0x1B, R20 // 133 __delay_cycles(OWI_DELAY_A_STD_MODE); LDI R19, 11 DEC R19 BRNE $-2 RJMP $+2 // 134 // 135 // Release bus and delay. // 136 OWI_RELEASE_BUS(pins); MOV R19, R17 COM R19 IN R20, 0x1A AND R20, R19 OUT 0x1A, R20 MOV R19, R17 COM R19 IN R20, 0x1B AND R20, R19 OUT 0x1B, R20 // 137 __delay_cycles(OWI_DELAY_E_STD_MODE); LDI R19, 19 DEC R19 BRNE $-2 RJMP $+2 // 138 // 139 // Sample bus and delay. // 140 bitsRead = OWI_PIN & pins; IN R19, 0x19 AND R19, R17 MOV R16, R19 // 141 __delay_cycles(OWI_DELAY_F_STD_MODE); LDI R19, 142 DEC R19 BRNE $-2 NOP // 142 // 143 // Restore interrupts. // 144 __restore_interrupt(intState); OUT 0x3F, R18 // 145 // 146 return bitsRead; RET REQUIRE _A_PORTA REQUIRE _A_DDRA 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 */ RSEG CODE:CODE:NOROOT(1) // 160 unsigned char OWI_DetectPresence(unsigned char pins) OWI_DetectPresence: // 161 { MOV R17, R16 // 162 unsigned char intState; // 163 unsigned char presenceDetected; // 164 // 165 // Disable interrupts. // 166 intState = __save_interrupt(); IN R19, 0x3F MOV R18, R19 // 167 __disable_interrupt(); CLI // 168 // 169 // Drive bus low and delay. // 170 OWI_PULL_BUS_LOW(pins); IN R19, 0x1A OR R19, R17 OUT 0x1A, R19 MOV R19, R17 COM R19 IN R20, 0x1B AND R20, R19 OUT 0x1B, R20 // 171 __delay_cycles(OWI_DELAY_H_STD_MODE); LDI R20, 188 LDI R21, 3 SUBI R20, 1 SBCI R21, 0 BRNE $-4 RJMP $+2 // 172 // 173 // Release bus and delay. // 174 OWI_RELEASE_BUS(pins); MOV R19, R17 COM R19 IN R20, 0x1A AND R20, R19 OUT 0x1A, R20 MOV R19, R17 COM R19 IN R20, 0x1B AND R20, R19 OUT 0x1B, R20 // 175 __delay_cycles(OWI_DELAY_I_STD_MODE); LDI R19, 182 DEC R19 BRNE $-2 NOP // 176 // 177 // Sample bus to detect presence signal and delay. // 178 presenceDetected = ((~OWI_PIN) & pins); IN R19, 0x19 COM R19 AND R19, R17 MOV R16, R19 // 179 __delay_cycles(OWI_DELAY_J_STD_MODE); LDI R20, 48 LDI R21, 3 SUBI R20, 1 SBCI R21, 0 BRNE $-4 RJMP $+2 // 180 // 181 // Restore interrupts. // 182 __restore_interrupt(intState); OUT 0x3F, R18 // 183 // 184 return presenceDetected; RET REQUIRE _A_PORTA REQUIRE _A_DDRA 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 */ RSEG CODE:CODE:NOROOT(1) // 197 void OWI_SendByte(unsigned char data, unsigned char pins) OWI_SendByte: // 198 { RCALL ?PROLOGUE4_L09 MOV R26, R16 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++) { LDI R24, 0 ??OWI_SendByte_0: CPI R24, 8 BRCC ??OWI_SendByte_1 // 204 // Determine if LSB is '0' or '1' and transmit corresponding // 205 // waveform on the bus. // 206 temp = data & 0x01; MOV R16, R26 ANDI R16, 0x01 MOV R27, R16 // 207 // 208 if (temp) { TST R27 BREQ ??OWI_SendByte_2 // 209 OWI_WriteBit1(pins); MOV R16, R25 RCALL OWI_WriteBit1 RJMP ??OWI_SendByte_3 // 210 } else { // 211 OWI_WriteBit0(pins); ??OWI_SendByte_2: MOV R16, R25 RCALL OWI_WriteBit0 // 212 } // 213 // 214 data >>= 1; // Right shift the data to get next bit. ??OWI_SendByte_3: LSR R26 // 215 } INC R24 RJMP ??OWI_SendByte_0 // 216 } ??OWI_SendByte_1: LDI R30, 4 RJMP ?EPILOGUE_B4_L09 // 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 */ RSEG CODE:CODE:NOROOT(1) // 228 unsigned char OWI_ReceiveByte(unsigned char pin) OWI_ReceiveByte: // 229 { RCALL ?PROLOGUE3_L09 MOV R26, R16 // 230 unsigned char data; // 231 unsigned char i; // 232 // 233 // Clear the temporary input variable. // 234 data = 0x00; LDI R25, 0 // 235 // 236 // Do once for each bit // 237 for (i = 0; i < 8; i++) { LDI R24, 0 ??OWI_ReceiveByte_0: CPI R24, 8 BRCC ??OWI_ReceiveByte_1 // 238 // Shift temporary input variable right. // 239 data >>= 1; 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)) { MOV R16, R26 RCALL OWI_ReadBit TST R16 BREQ ??OWI_ReceiveByte_2 // 244 data |= 0x80; ORI R25, 0x80 LDI R16, 1 // 245 } // 246 } ??OWI_ReceiveByte_2: INC R24 RJMP ??OWI_ReceiveByte_0 // 247 // 248 return data; ??OWI_ReceiveByte_1: MOV R16, R25 LDI R30, 3 RJMP ?EPILOGUE_B3_L09 // 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 */ RSEG CODE:CODE:NOROOT(1) // 256 void OWI_SkipRom(unsigned char pins) OWI_SkipRom: // 257 { ST -Y, R24 MOV R24, R16 // 258 // Send the SKIP ROM command on the bus. // 259 OWI_SendByte(OWI_ROM_SKIP, pins); MOV R17, R24 LDI R16, 204 RCALL OWI_SendByte // 260 } LD R24, Y+ RET // 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 */ RSEG CODE:CODE:NOROOT(1) // 269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin) OWI_ReadRom: // 270 { RCALL ?PROLOGUE4_L09 MOVW R27:R26, R17:R16 MOV R25, R18 // 271 unsigned char bytesLeft = 8; LDI R24, 8 // 272 // 273 // Send the READ ROM command on the bus. // 274 OWI_SendByte(OWI_ROM_READ, pin); MOV R17, R25 LDI R16, 51 RCALL OWI_SendByte // 275 // 276 // Do 8 times. // 277 while (bytesLeft > 0) { ??OWI_ReadRom_0: CPI R24, 1 BRCS ??OWI_ReadRom_1 // 278 // Place the received data in memory. // 279 *romValue++ = OWI_ReceiveByte(pin); MOV R16, R25 RCALL OWI_ReceiveByte ST X, R16 ADIW R27:R26, 1 // 280 bytesLeft--; DEC R24 RJMP ??OWI_ReadRom_0 // 281 } // 282 } ??OWI_ReadRom_1: LDI R30, 4 RJMP ?EPILOGUE_B4_L09 // 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 */ RSEG CODE:CODE:NOROOT(1) // 291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins) OWI_MatchRom: // 292 { RCALL ?PROLOGUE4_L09 MOVW R27:R26, R17:R16 MOV R25, R18 // 293 unsigned char bytesLeft = 8; LDI R24, 8 // 294 // 295 // Send the MATCH ROM command. // 296 OWI_SendByte(OWI_ROM_MATCH, pins); MOV R17, R25 LDI R16, 85 RCALL OWI_SendByte // 297 // 298 // Do once for each byte. // 299 while (bytesLeft > 0) { ??OWI_MatchRom_0: CPI R24, 1 BRCS ??OWI_MatchRom_1 // 300 // Transmit 1 byte of the ID to match. // 301 OWI_SendByte(*romValue++, pins); MOV R17, R25 LD R16, X RCALL OWI_SendByte ADIW R27:R26, 1 // 302 bytesLeft--; DEC R24 RJMP ??OWI_MatchRom_0 // 303 } // 304 } ??OWI_MatchRom_1: LDI R30, 4 RJMP ?EPILOGUE_B4_L09 // 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 */ RSEG CODE:CODE:NOROOT(1) // 333 unsigned char OWI_SearchRom(unsigned char * bitPattern, OWI_SearchRom: // 334 unsigned char lastDeviation, unsigned char pin) // 335 { RCALL ?PROLOGUE9_L09 REQUIRE ?Register_R4_is_cg_reg REQUIRE ?Register_R5_is_cg_reg REQUIRE ?Register_R6_is_cg_reg REQUIRE ?Register_R7_is_cg_reg REQUIRE ?Register_R8_is_cg_reg MOVW R5:R4, R17:R16 MOV R8, R18 MOV R27, R19 // 336 unsigned char currentBit = 1; LDI R24, 1 // 337 unsigned char newDeviation = 0; LDI R26, 0 // 338 unsigned char bitMask = 0x01; 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); MOV R17, R27 LDI R16, 240 RCALL OWI_SendByte // 344 // 345 // Walk through all 64 bits. // 346 while (currentBit <= 64) { ??OWI_SearchRom_0: CPI R24, 65 BRCS $+2+2 RJMP ??OWI_SearchRom_1 // 347 // Read bit from bus twice. // 348 bitA = OWI_ReadBit(pin); MOV R16, R27 RCALL OWI_ReadBit MOV R6, R16 // 349 bitB = OWI_ReadBit(pin); MOV R16, R27 RCALL OWI_ReadBit MOV R7, R16 // 350 // 351 if (bitA && bitB) { TST R6 BREQ ??OWI_SearchRom_2 TST R7 BREQ ??OWI_SearchRom_2 // 352 // Both bits 1 (Error). // 353 newDeviation = OWI_ROM_SEARCH_FAILED; LDI R26, 255 // 354 return newDeviation; MOV R16, R26 RJMP ??OWI_SearchRom_3 // 355 } else if (bitA ^ bitB) { ??OWI_SearchRom_2: MOV R16, R7 EOR R16, R6 TST R16 BREQ ??OWI_SearchRom_4 // 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) { TST R6 BREQ ??OWI_SearchRom_5 // 359 (*bitPattern) |= bitMask; MOVW R31:R30, R5:R4 LD R16, Z OR R16, R25 ST Z, R16 RJMP ??OWI_SearchRom_6 // 360 } else { // 361 (*bitPattern) &= ~bitMask; ??OWI_SearchRom_5: MOV R16, R25 COM R16 MOVW R31:R30, R5:R4 LD R17, Z AND R17, R16 ST Z, R17 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_4: CP R24, R8 BRNE ??OWI_SearchRom_7 // 367 (*bitPattern) |= bitMask; MOVW R31:R30, R5:R4 LD R16, Z OR R16, R25 ST Z, R16 RJMP ??OWI_SearchRom_6 // 368 } // 369 // 370 // For the rest of the id, '0' bits are selected when // 371 // discrepancies occur. // 372 else if (currentBit > lastDeviation) { ??OWI_SearchRom_7: CP R8, R24 BRCC ??OWI_SearchRom_8 // 373 (*bitPattern) &= ~bitMask; MOV R16, R25 COM R16 MOVW R31:R30, R5:R4 LD R17, Z AND R17, R16 ST Z, R17 // 374 newDeviation = currentBit; MOV R26, R24 RJMP ??OWI_SearchRom_6 // 375 } // 376 // 377 // If current bit in bit pattern = 0, then this is // 378 // out new deviation. // 379 else if ( !(*bitPattern & bitMask)) { ??OWI_SearchRom_8: MOVW R31:R30, R5:R4 LD R16, Z AND R16, R25 TST R16 BRNE ??OWI_SearchRom_6 // 380 newDeviation = currentBit; MOV R26, 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: MOVW R31:R30, R5:R4 LD R16, Z AND R16, R25 TST R16 BREQ ??OWI_SearchRom_9 // 390 OWI_WriteBit1(pin); MOV R16, R27 RCALL OWI_WriteBit1 RJMP ??OWI_SearchRom_10 // 391 } else { // 392 OWI_WriteBit0(pin); ??OWI_SearchRom_9: MOV R16, R27 RCALL OWI_WriteBit0 // 393 } // 394 // 395 // Increment current bit. // 396 currentBit++; ??OWI_SearchRom_10: INC R24 // 397 // 398 // Adjust bitMask and bitPattern pointer. // 399 bitMask <<= 1; LSL R25 // 400 if (!bitMask) { TST R25 BREQ $+2+2 RJMP ??OWI_SearchRom_0 // 401 bitMask = 0x01; LDI R25, 1 // 402 bitPattern++; LDI R16, 1 ADD R4, R16 LDI R16, 0 ADC R5, R16 RJMP ??OWI_SearchRom_0 // 403 } // 404 } // 405 // 406 return newDeviation; ??OWI_SearchRom_1: MOV R16, R26 ??OWI_SearchRom_3: LDI R30, 9 RJMP ?EPILOGUE_B9_L09 // 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 */ RSEG CODE:CODE:NOROOT(1) // 428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) OWI_ComputeCRC8: // 429 { MOV R19, R16 MOV R16, R17 // 430 unsigned char bitsLeft; // 431 unsigned char temp; // 432 // 433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { LDI R17, 8 ??OWI_ComputeCRC8_0: CPI R17, 1 BRCS ??OWI_ComputeCRC8_1 // 434 temp = ((seed ^ inData) & 0x01); MOV R21, R16 ANDI R21, 0x01 MOV R18, R19 ANDI R18, 0x01 EOR R18, R21 ANDI R18, 0x01 MOV R20, R18 // 435 // 436 if (temp == 0) { TST R20 BRNE ??OWI_ComputeCRC8_2 // 437 seed >>= 1; LSR R16 RJMP ??OWI_ComputeCRC8_3 // 438 } else { // 439 seed ^= 0x18; ??OWI_ComputeCRC8_2: LDI R18, 24 EOR R16, R18 // 440 seed >>= 1; LSR R16 // 441 seed |= 0x80; ORI R16, 0x80 LDI R18, 1 // 442 } // 443 // 444 inData >>= 1; ??OWI_ComputeCRC8_3: LSR R19 // 445 } DEC R17 RJMP ??OWI_ComputeCRC8_0 // 446 return seed; ??OWI_ComputeCRC8_1: 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 */ RSEG CODE:CODE:NOROOT(1) // 467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) OWI_ComputeCRC16: // 468 { MOV R21, R16 // 469 unsigned char bitsLeft; // 470 unsigned char temp; // 471 // 472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { LDI R20, 8 ??OWI_ComputeCRC16_0: CPI R20, 1 BRCS ??OWI_ComputeCRC16_1 // 473 temp = ((seed ^ inData) & 0x01); MOV R17, R18 ANDI R17, 0x01 MOV R16, R21 ANDI R16, 0x01 EOR R16, R17 ANDI R16, 0x01 MOV R22, R16 // 474 // 475 if (temp == 0) { TST R22 BRNE ??OWI_ComputeCRC16_2 // 476 seed >>= 1; LSR R19 ROR R18 RJMP ??OWI_ComputeCRC16_3 // 477 } else { // 478 seed ^= 0x4002; ??OWI_ComputeCRC16_2: LDI R16, 2 LDI R17, 64 EOR R18, R16 EOR R19, R17 // 479 seed >>= 1; LSR R19 ROR R18 // 480 seed |= 0x8000; ORI R19, 0x80 LDI R16, 1 LDI R17, 0 // 481 } // 482 // 483 inData >>= 1; ??OWI_ComputeCRC16_3: LSR R21 // 484 } DEC R20 RJMP ??OWI_ComputeCRC16_0 // 485 // 486 return seed; ??OWI_ComputeCRC16_1: MOVW R17:R16, R19:R18 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 */ RSEG CODE:CODE:NOROOT(1) // 501 unsigned char OWI_CheckRomCRC(unsigned char *romValue) OWI_CheckRomCRC: // 502 { RCALL ?PROLOGUE4_L09 MOVW R27:R26, R17:R16 // 503 unsigned char i; // 504 unsigned char crc8 = 0; LDI R25, 0 // 505 // 506 for (i = 0; i < 7; i++) { LDI R24, 0 ??OWI_CheckRomCRC_0: CPI R24, 7 BRCC ??OWI_CheckRomCRC_1 // 507 crc8 = OWI_ComputeCRC8(*romValue, crc8); MOV R17, R25 MOVW R31:R30, R27:R26 LD R16, Z RCALL OWI_ComputeCRC8 MOV R25, R16 // 508 romValue++; ADIW R27:R26, 1 // 509 } INC R24 RJMP ??OWI_CheckRomCRC_0 // 510 // 511 if (crc8 == (*romValue)) { ??OWI_CheckRomCRC_1: LD R16, X CP R25, R16 BRNE ??OWI_CheckRomCRC_2 // 512 return OWI_CRC_OK; LDI R16, 0 RJMP ??OWI_CheckRomCRC_3 // 513 } // 514 // 515 return OWI_CRC_ERROR; ??OWI_CheckRomCRC_2: LDI R16, 1 ??OWI_CheckRomCRC_3: LDI R30, 4 RJMP ?EPILOGUE_B4_L09 // 516 } ASEGN ABSOLUTE:DATA:NOROOT,01cH __?EECR: ASEGN ABSOLUTE:DATA:NOROOT,01dH __?EEDR: ASEGN ABSOLUTE:DATA:NOROOT,01eH __?EEARL: ASEGN ABSOLUTE:DATA:NOROOT,01fH __?EEARH: END // // 3 bytes in segment ABSOLUTE // 820 bytes in segment CODE // // 820 bytes of CODE memory // 0 bytes of DATA memory (+ 3 bytes shared) // //Errors: none //Warnings: none