Implementation of 1-Wire with added Alarm Search Functionality
Dependents: Max32630_One_Wire_Interface
Diff: OneWire_Masters/OneWireMaster.cpp
- Revision:
- 32:bce180b544ed
- Parent:
- 27:d5aaefa252f1
- Child:
- 36:b6b5985a5e40
--- a/OneWire_Masters/OneWireMaster.cpp Tue Mar 29 16:36:12 2016 -0500 +++ b/OneWire_Masters/OneWireMaster.cpp Wed Mar 30 16:50:29 2016 -0500 @@ -41,22 +41,20 @@ const uint16_t OneWireMaster::_oddparity[] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; -OneWireMaster::CmdResult OneWireMaster::OWFirst(RomId & romId) +OneWireMaster::CmdResult OneWireMaster::OWFirst(SearchState & searchState) { // reset the search state - _last_discrepancy = 0; - _last_device_flag = 0; - _last_family_discrepancy = 0; + searchState.reset(); - return OWSearch(romId); + return OWSearch(searchState); } //********************************************************************* -OneWireMaster::CmdResult OneWireMaster::OWNext(RomId & romId) +OneWireMaster::CmdResult OneWireMaster::OWNext(SearchState & searchState) { // leave the search state alone - return OWSearch(romId); + return OWSearch(searchState); } @@ -64,66 +62,50 @@ OneWireMaster::CmdResult OneWireMaster::OWVerify(const RomId & romId) { OneWireMaster::CmdResult result; - RomId romIdCopy(romId); - int ld_backup, ldf_backup, lfd_backup; - - // keep a backup copy of the current state - ld_backup = _last_discrepancy; - ldf_backup = _last_device_flag; - lfd_backup = _last_family_discrepancy; + SearchState searchState; // set search to find the same device - _last_discrepancy = 64; - _last_device_flag = false; + searchState.last_discrepancy = 64; + searchState.last_device_flag = false; - result = OWSearch(romIdCopy); + result = OWSearch(searchState); if (result == OneWireMaster::Success) { // check if same device found - if (romId != romIdCopy) + if (romId != searchState.romId) { result = OneWireMaster::OperationFailure; } } - // restore the search state - _last_discrepancy = ld_backup; - _last_device_flag = ldf_backup; - _last_family_discrepancy = lfd_backup; - - // return the result of the verify return result; } //********************************************************************* -void OneWireMaster::OWTargetSetup(RomId & romId) +void OneWireMaster::OWTargetSetup(SearchState & searchState) { // set the search state to find SearchFamily type devices - for (int i = 1; i < 8; i++) - { - romId[i] = 0; - } - - _last_discrepancy = 64; - _last_family_discrepancy = 0; - _last_device_flag = false; + std::uint8_t familyCode = searchState.romId.familyCode(); + searchState.reset(); + searchState.romId.setFamilyCode(familyCode); + searchState.last_discrepancy = 64; } //********************************************************************* -void OneWireMaster::OWFamilySkipSetup(void) +void OneWireMaster::OWFamilySkipSetup(SearchState & searchState) { // set the Last discrepancy to last family discrepancy - _last_discrepancy = _last_family_discrepancy; + searchState.last_discrepancy = searchState.last_family_discrepancy; // clear the last family discrpepancy - _last_family_discrepancy = 0; + searchState.last_family_discrepancy = 0; // check for end of list - if (_last_discrepancy == 0) + if (searchState.last_discrepancy == 0) { - _last_device_flag = true; + searchState.last_device_flag = true; } } @@ -195,7 +177,7 @@ //********************************************************************* OneWireMaster::CmdResult OneWireMaster::OWOverdriveSkipROM(void) { - OneWireMaster::CmdResult result = OWSpeed(SPEED_STANDARD); + OneWireMaster::CmdResult result = OWSetSpeed(SPEED_STANDARD); if (result == OneWireMaster::Success) { @@ -209,7 +191,7 @@ if (result == OneWireMaster::Success) { - result = OWSpeed(SPEED_OVERDRIVE); + result = OWSetSpeed(SPEED_OVERDRIVE); } return result; @@ -222,7 +204,7 @@ OneWireMaster::CmdResult result; // use overdrive MatchROM - OWSpeed(SPEED_STANDARD); + OWSetSpeed(SPEED_STANDARD); result = OWReset(); if (result == OneWireMaster::Success) @@ -230,7 +212,7 @@ result = OWWriteByte(OVERDRIVE_MATCH_ROM); if (result == OneWireMaster::Success) { - OWSpeed(SPEED_OVERDRIVE); + OWSetSpeed(SPEED_OVERDRIVE); // send ROM result = OWWriteBlock(romId, RomId::byteLen); } @@ -254,6 +236,146 @@ } +OneWireMaster::CmdResult OneWireMaster::OWSearch(SearchState & searchState) +{ + std::uint8_t id_bit_number; + std::uint8_t last_zero, rom_byte_number; + std::uint8_t id_bit, cmp_id_bit; + std::uint8_t rom_byte_mask, status; + bool search_result; + std::uint8_t crc8 = 0; + SearchDirection search_direction; + + // initialize for search + id_bit_number = 1; + last_zero = 0; + rom_byte_number = 0; + rom_byte_mask = 1; + search_result = false; + + // if the last call was not the last one + if (!searchState.last_device_flag) + { + // 1-Wire reset + OneWireMaster::CmdResult result = OWReset(); + if (result != OneWireMaster::Success) + { + // reset the search + searchState.reset(); + return result; + } + + // issue the search command + OneWireMaster::OWWriteByte(SEARCH_ROM); + + // loop to do the search + do + { + // if this discrepancy if before the Last Discrepancy + // on a previous next then pick the same as last time + if (id_bit_number < searchState.last_discrepancy) + { + if ((searchState.romId[rom_byte_number] & rom_byte_mask) > 0) + search_direction = DIRECTION_WRITE_ONE; + else + search_direction = DIRECTION_WRITE_ZERO; + } + else + { + // if equal to last pick 1, if not then pick 0 + if (id_bit_number == searchState.last_discrepancy) + search_direction = DIRECTION_WRITE_ONE; + else + search_direction = DIRECTION_WRITE_ZERO; + } + + // Peform a triple operation on the DS2465 which will perform 2 read bits and 1 write bit + result = OWTriplet(search_direction, id_bit, cmp_id_bit); + if (result != OneWireMaster::Success) + return result; + + // check for no devices on 1-wire + if ((id_bit) && (cmp_id_bit)) + break; + else + { + if ((!id_bit) && (!cmp_id_bit) && (search_direction == DIRECTION_WRITE_ZERO)) + { + last_zero = id_bit_number; + + // check for Last discrepancy in family + if (last_zero < 9) + searchState.last_family_discrepancy = last_zero; + } + + // set or clear the bit in the ROM byte rom_byte_number + // with mask rom_byte_mask + if (search_direction == DIRECTION_WRITE_ONE) + searchState.romId[rom_byte_number] |= rom_byte_mask; + else + searchState.romId[rom_byte_number] &= (std::uint8_t)~rom_byte_mask; + + // increment the byte counter id_bit_number + // and shift the mask rom_byte_mask + id_bit_number++; + rom_byte_mask <<= 1; + + // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask + if (rom_byte_mask == 0) + { + crc8 = RomId::calculateCRC8(crc8, searchState.romId[rom_byte_number]); // accumulate the CRC + rom_byte_number++; + rom_byte_mask = 1; + } + } + } + while(rom_byte_number < RomId::byteLen); // loop until through all ROM bytes 0-7 + + // if the search was successful then + if (!((id_bit_number <= (RomId::byteLen * 8)) || (crc8 != 0))) + { + // search successful so set m_last_discrepancy,m_last_device_flag,search_result + searchState.last_discrepancy = last_zero; + + // check for last device + if (searchState.last_discrepancy == 0) + searchState.last_device_flag = true; + + search_result = true; + } + } + + // if no device found then reset counters so next 'search' will be like a first + if (!search_result || (searchState.romId.familyCode() == 0)) + { + searchState.reset(); + search_result = false; + } + + return search_result ? OneWireMaster::Success : OneWireMaster::OperationFailure; +} + + +OneWireMaster::CmdResult OneWireMaster::OWTriplet(SearchDirection & search_direction, std::uint8_t & sbr, std::uint8_t & tsb) +{ + CmdResult result; + result = OWReadBit(sbr); + if (result == Success) + result = OWReadBit(tsb); + if (result == Success) + { + if (sbr == 1) + search_direction = DIRECTION_WRITE_ONE; + else if ((sbr == 0) && (tsb == 1)) + search_direction = DIRECTION_WRITE_ZERO; + // else: use search_direction parameter + + result = OWWriteBit((search_direction == DIRECTION_WRITE_ONE) ? 1 : 0); + } + return result; +} + + //-------------------------------------------------------------------------- // Calculate a new CRC16 from the input data shorteger. Return the current // CRC16 and also update the global variable CRC16.