Library to communicate with Maxim OneWire protocol devices Modified timings and IRQ overrides
Fork of Onewire by
Onewire.cpp
- Committer:
- Bobty
- Date:
- 2015-10-15
- Revision:
- 7:0a87f8c2d9e6
- Parent:
- 6:d2452e9b169b
- Child:
- 8:5d0bd95b586f
File content as of revision 7:0a87f8c2d9e6:
// 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
oneBus_.output();
oneBus_ = 0;
wait_us(12);
oneBus_.input();
wait_us(60);
}
else
{
// Write '0' bit
oneBus_.output();
oneBus_ = 0;
wait_us(60);
oneBus_.input();
wait_us(12);
}
__enable_irq();
}
int Onewire::readBit()
{
char result;
__disable_irq();
oneBus_.output();
oneBus_ = 0;
wait_us(5);
oneBus_.input();
wait_us(7);
result = oneBus_.read();
wait_us(60);
__enable_irq();
return result;
}
int Onewire::init()
{
oneBus_.output();
oneBus_ = 0;
wait_us(480);
__disable_irq();
oneBus_.input();
wait_us(60);
if (oneBus_.read() == 0)
{
__enable_irq();
wait_us(100);
return ONEWIRE_OK;
}
__enable_irq();
return 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();
wait_us(410);
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_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_STUCK_HIGH: return "Stuck High";
case ONEWIRE_SEARCH_COMP_BIT_ERR: return "Comp Bit Err";
}
return "Unknown Err";
}
