This file is part of OneWire routines
This is file "OneWire.c"/*============================================================================*/ /* Copyright (c) 2016-2019, Isaac Marino Bavaresco All rights reserved. isaacbavaresco@yahoo.com.br Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*============================================================================*/ #include <string.h> #include <xc.h> #include "OneWire.h" /*============================================================================*/ static onewirestatus_t OneWireWriteBit( onewireint_t Value ) { if( Value ) return OneWireWriteOne(); else return OneWireWriteZero(); } /*============================================================================*/ onewirestatus_t OneWireWriteByte( unsigned char Value ) { onewirestatus_t Status; onewireint_t BitNumber; for( BitNumber = 0; BitNumber < 8; BitNumber++, Value >>= 1 ) { if(( Status = OneWireWriteBit( Value & 0x01 )) != ONE_WIRE_STATUS_OK ) return Status; } return ONE_WIRE_STATUS_OK; } /*============================================================================*/ int OneWireReadByte( void ) { unsigned char Value; onewirestatus_t Status; onewireint_t BitNumber; for( BitNumber = 0, Value = 0; BitNumber < 8; BitNumber++ ) { if(( Status = OneWireReadBit() ) < ONE_WIRE_STATUS_OK ) return (int)Status; Value = (unsigned char)(( Value >> 1 ) | ( Status > ONE_WIRE_STATUS_OK ? 0x80 : 0x00 )); } return (unsigned int)Value; } /*============================================================================*/ unsigned char CalcCRC8( unsigned char Seed, unsigned char Value ) { static const unsigned char CRC8Table[256] = { 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 }; return CRC8Table[(unsigned char)( Seed ^ Value )]; } /*============================================================================*/ onewirestatus_t OneWireMatchROM( const ibuttonsn_t *SerialNumber ) { onewirestatus_t Status; onewireint_t i; if(( Status = OneWireWriteByte( ONE_WIRE_COMMAND_MATCH_ROM )) != ONE_WIRE_STATUS_OK ) return Status; for( i = 0; i < (onewireint_t)sizeof *SerialNumber; i++ ) { if(( Status = OneWireWriteByte( SerialNumber->Bytes[i] )) != ONE_WIRE_STATUS_OK ) return Status; } return ONE_WIRE_STATUS_OK; } /*============================================================================*/ onewirestatus_t OneWireReadSerialNumber( ibuttonsn_t *SerialNumber ) { unsigned char CRC; onewirestatus_t Status; onewireint_t i; int Result; if(( Status = OneWireReset() ) != ONE_WIRE_STATUS_OK ) return Status; if(( Status = OneWireWriteByte( ONE_WIRE_COMMAND_READ_ROM )) != ONE_WIRE_STATUS_OK ) return Status; for( CRC = 0, i = 0; i < ONE_WIRE_SERIAL_NUMBER_SIZE; i++ ) { if(( Result = OneWireReadByte() ) < ONE_WIRE_STATUS_OK ) return (onewirestatus_t)Result; CRC = CalcCRC8( CRC, SerialNumber->Bytes[i] = (unsigned char)Result ); } if( CRC != 0 ) return ONE_WIRE_STATUS_CRC_ERROR; else return ONE_WIRE_STATUS_OK; } /*============================================================================*/ /*============================================================================*/ #if defined USE_INLINE static inline onewirestatus_t BitVectorExtract( unsigned char *V, onewireint_t Bit ) { return ( V[ Bit / 8 ] >> Bit % 8 ) & 0x01; } #else /* defined USE_INLINE */ #define BitVectorExtract(v,b) (((v)[(b)>>3]>>((b)&7))&0x01) #endif /* defined USE_INLINE */ /*============================================================================*/ #if defined USE_INLINE static inline void BitVectorInsert( unsigned char *V, onewireint_t Bit, onewireint_t Value ) { V[ Bit / 8 ] = ( V[ Bit / 8 ] & ~( 1 << Bit % 8 )) | (( Value & 0x01 ) << Bit % 8 ); } #else /* defined USE_INLINE */ #define BitVectorInsert(v,b,l) ((v)[(b)>>3]=((v)[(b)>>3]&~(1<<((b)&7)))|(((l)&0x01)<<((b)&7))) #endif /* defined USE_INLINE */ /*============================================================================*/ void OneWireSearchInit( onewiresearch_t *SearchStruct, int FamilyCode ) { memset( SearchStruct->SerialNumber, 0x00, sizeof SearchStruct->SerialNumber ); memset( SearchStruct->Branches, 0x00, sizeof SearchStruct->Branches ); if( FamilyCode >= 0 && FamilyCode <= 255 ) { SearchStruct->SerialNumber[0] = (unsigned char)FamilyCode; SearchStruct->NumberOfFixedBits = 8; } else SearchStruct->NumberOfFixedBits = 0; SearchStruct->FirstSearch = 1; SearchStruct->Finished = 0; } /*============================================================================*/ onewirestatus_t OneWireSearch( onewiresearch_t *SearchStruct, ibuttonsn_t *SerialNumber ) { onewirestatus_t BitTrue, BitNegated, CurrentBit; onewirestatus_t Status; onewireint_t BitNumber; if( SearchStruct->Finished != 0 ) return ONE_WIRE_SEARCH_STATUS_NOT_FOUND; if(( Status = OneWireReset() ) != ONE_WIRE_STATUS_OK ) return Status; /* If this is not the first search iteration we must unwind the tree before starting the next iteration. */ if( SearchStruct->FirstSearch == 0 ) { /* We start at a leaf of the tree and walk up until we reach the closest branch where we took a left turn and then switch it to a right turn (set serial number bit), while we zero the bits for all other occurrences. */ for( BitNumber = 8 * ONE_WIRE_SERIAL_NUMBER_SIZE - 1; BitNumber >= SearchStruct->NumberOfFixedBits; BitNumber-- ) { if( BitVectorExtract( SearchStruct->Branches, BitNumber ) == 1 && BitVectorExtract( SearchStruct->SerialNumber, BitNumber ) == 0 ) { BitVectorInsert( SearchStruct->SerialNumber, BitNumber, 1 ); break; } BitVectorInsert( SearchStruct->SerialNumber, BitNumber, 0 ); BitVectorInsert( SearchStruct->Branches, BitNumber, 0 ); } if( BitNumber < SearchStruct->NumberOfFixedBits ) { SearchStruct->Finished = 1; return ONE_WIRE_SEARCH_STATUS_NOT_FOUND; } } SearchStruct->FirstSearch = 0; /* Issue the command SEARCH ROM to all devices on the bus. */ if(( Status = OneWireWriteByte( ONE_WIRE_COMMAND_SEARCH_ROM )) != ONE_WIRE_STATUS_OK ) return Status; /* Walk down the tree marking the branches and taking the left path unless in a previous excursion we already took the left path. */ for( BitNumber = 0; BitNumber < 8 * ONE_WIRE_SERIAL_NUMBER_SIZE; BitNumber++ ) { /* Read the logical AND of the true values of the bits in this position of all devices on the bus. */ if(( BitTrue = OneWireReadBit() ) < ONE_WIRE_STATUS_OK ) /* ...but an error happened. */ return BitTrue; /* Read the logical AND of the negated values of the bits in this position of all devices on the bus. */ if(( BitNegated = OneWireReadBit() ) < ONE_WIRE_STATUS_OK ) /* ...but an error happened. */ return BitNegated; /* There was no response... */ if( BitTrue == 1 && BitNegated == 1 ) { SearchStruct->Finished = 1; return ONE_WIRE_STATUS_NO_RESPONSE; } /* We are searching devices with a specific bit value in this position... */ if( BitNumber < SearchStruct->NumberOfFixedBits ) { /* ...get the value that we want for the bit. */ CurrentBit = BitVectorExtract( SearchStruct->SerialNumber, BitNumber ); /* No device on the bus has the value we are expecting in this bit position... */ if( CurrentBit != BitTrue ) /* ...return a NOT FOUND status. */ return ONE_WIRE_SEARCH_STATUS_NOT_FOUND; } /* We found at least two devices with opposite bit values in this bit position... */ else if( BitTrue == 0 && BitNegated == 0 ) { /* ...so we mark that there is a branch in this position... */ BitVectorInsert( SearchStruct->Branches, BitNumber, 1 ); /* ...and get the value we want to select. */ CurrentBit = BitVectorExtract( SearchStruct->SerialNumber, BitNumber ); } /* All devices on the bus have the same value in this bit position... */ else { /* ...so we save the value of the bit found. */ BitVectorInsert( SearchStruct->SerialNumber, BitNumber, BitTrue ); CurrentBit = BitTrue; } /* Send the bit value to select only the devices that have the value we want in this bit position. */ if(( Status = OneWireWriteBit( CurrentBit )) != ONE_WIRE_STATUS_OK ) /* ...but an error happened. */ return Status; } /* Save the serial number of the device that we just found... */ memcpy( SerialNumber, SearchStruct->SerialNumber, sizeof SearchStruct->SerialNumber ); /* ...and return a success status. */ return ONE_WIRE_SEARCH_STATUS_FOUND; } /*============================================================================*/