Library to communicate with Maxim OneWire protocol devices Modified timings and IRQ overrides
Fork of Onewire by
Onewire.cpp
- Committer:
- Bobty
- Date:
- 2015-10-16
- Revision:
- 8:5d0bd95b586f
- Parent:
- 7:0a87f8c2d9e6
File content as of revision 8:5d0bd95b586f:
// Code derived from a number of sources including: // simonbarker on MBED // The search code is a port of Jim Studt's Adruino One Wire lib // Can handle multiple devices per pin // Rob Dobson, 2015 #include "Onewire.h" Onewire::Onewire(PinName oneBus):oneBus_(oneBus) { } void Onewire::writeBit(int bit) { __disable_irq(); bit = bit & 0x01; if (bit) { // Write '1' bit __disable_irq(); oneBus_.output(); oneBus_ = 0; wait_us(10); oneBus_ = 1; __enable_irq(); wait_us(55); } else { // Write '0' bit __disable_irq(); oneBus_.output(); oneBus_ = 0; wait_us(65); oneBus_ = 1; __enable_irq(); wait_us(5); } __enable_irq(); } int Onewire::readBit() { char result; __disable_irq(); oneBus_.output(); oneBus_ = 0; wait_us(3); oneBus_.input(); wait_us(10); result = oneBus_.read(); __enable_irq(); wait_us(53); return result; } int Onewire::init() { // Ensure bus is high to start oneBus_.input(); int MAX_RETRY_TEST_BUS_HIGH = 125; for (int i = 0; i < MAX_RETRY_TEST_BUS_HIGH; i++) { if (oneBus_.read() == 1) break; wait_us(2); } if (oneBus_.read() != 1) return ONEWIRE_FAIL_STUCK_LOW; // Pull LOW for 480us __disable_irq(); oneBus_.output(); oneBus_ = 0; __enable_irq(); wait_us(480); // Allow to float and test to ensure presence of devices // (which pull the bus low) __disable_irq(); oneBus_.input(); wait_us(70); int readVal = oneBus_.read(); __enable_irq(); wait_us(410); return (readVal == 0) ? ONEWIRE_OK : ONEWIRE_SEARCH_INIT_FAIL; } int Onewire::readByte() { int result = 0; for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) { // shift the result to get it ready for the next bit result >>= 1; // if result is one, then set MS bit if (readBit()) result |= 0x80; } return result; } void Onewire::writeByte(char data) { // Loop to write each bit in the byte, LS-bit first for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) { writeBit(data & 0x01); // shift the data byte for the next bit data >>= 1; } } unsigned char Onewire::CRC(unsigned char* addr, unsigned char len) { unsigned char i, j; unsigned char crc = 0; for (i = 0; i < len; i++) { unsigned char inbyte = addr[i]; for (j = 0; j < ONEWIRE_ADDR_BYTES; j++) { unsigned char mix = (crc ^ inbyte) & 0x01; crc >>= 1; if (mix) crc ^= 0x8C; inbyte >>= 1; } } return crc; } // // You need to use this function to start a search again from the beginning. // You do not need to do it for the first search, though you could. // void Onewire::reset_search() { // reset the search state _search_LastDiscrepancy = 0; _search_LastDeviceFlag = false; _search_LastFamilyDiscrepancy = 0; for(int i = ONEWIRE_ADDR_BYTES-1; i >= 0; i--) _search_ROM_NO[i] = 0; } // Search Based on Maxim DS18B20 Algorithm // https://www.maximintegrated.com/en/app-notes/index.mvp/id/187 // // Perform a search, returns: // ONEWIRE_OK if a new address has been returned. // ONEWIRE_SEARCH_ALL_DONE = all devices found // ONEWIRE_SEARCH_INIT_FAIL = failed to init // ONEWIRE_SEARCH_NOT_FOUND = no devices found If this function returns a '1' then it has // ONEWIRE_SEARCH_STUCK_HIGH = bus is stuck high // ONEWIRE_SEARCH_COMP_BIT_ERR = complement bit error // uint8_t Onewire::search(uint8_t *newAddr) { // initialize for search uint8_t last_zero = 0; unsigned char search_direction = 0; // if the previous call was the last one if (_search_LastDeviceFlag) return ONEWIRE_SEARCH_ALL_DONE; // 1-Wire reset int initRslt = init(); if (initRslt != ONEWIRE_OK) { // reset the search reset_search(); return initRslt; } // issue the search command writeByte(0xF0); // loop to do the search for (int id_bit_number = 1; id_bit_number <= 64; id_bit_number++) { // read a bit and its complement uint8_t id_bit = readBit(); uint8_t cmp_id_bit = readBit(); // check for no devices on 1-wire if ((id_bit == 1) && (cmp_id_bit == 1)) { reset_search(); return ONEWIRE_SEARCH_COMP_BIT_ERR; } // all devices coupled have 0 or 1 int byteNo = (id_bit_number - 1) / 8; int byteMask = 1 << ((id_bit_number - 1) % 8); if (id_bit != cmp_id_bit) { search_direction = id_bit; // bit write value for search } else { if (id_bit_number == _search_LastDiscrepancy) { search_direction = 1; } else if (id_bit_number > _search_LastDiscrepancy) { search_direction = 0; } else { search_direction = ((_search_ROM_NO[byteNo] & byteMask) > 0); } // if 0 was picked then record its position in LastZero if (search_direction == 0) { last_zero = id_bit_number; // check for Last discrepancy in family if (last_zero < 9) _search_LastFamilyDiscrepancy = last_zero; } } // set or clear the bit in the ROM byte rom_byte_number // with mask rom_byte_mask if (search_direction == 1) _search_ROM_NO[byteNo] |= byteMask; else _search_ROM_NO[byteNo] &= ~byteMask; // serial number search direction write bit writeBit(search_direction); } // search successful so set LastDiscrepancy,LastDeviceFlag,search_result _search_LastDiscrepancy = last_zero; // check for last device if (_search_LastDiscrepancy == 0) _search_LastDeviceFlag = true; // Copy address to return for (int i = 0; i < ONEWIRE_ADDR_BYTES; i++) newAddr[i] = _search_ROM_NO[i]; return ONEWIRE_OK; } char* Onewire::GetErrorStr(int errCode) { switch(errCode) { case ONEWIRE_OK: return "OK"; case ONEWIRE_FAIL_STUCK_LOW: return "Stuck Low"; case ONEWIRE_SEARCH_ALL_DONE: return "All Done"; case ONEWIRE_SEARCH_INIT_FAIL: return "Init Fail"; case ONEWIRE_SEARCH_NOT_FOUND: return "Not Found"; case ONEWIRE_SEARCH_COMP_BIT_ERR: return "Comp Bit Err"; } return "Unknown Err"; }