Library to communicate with Maxim OneWire protocol devices Modified timings and IRQ overrides

Dependents:   RdGasUseMonitor

Fork of Onewire by Simon Barker

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Onewire.cpp Source File

Onewire.cpp

00001 // Code derived from a number of sources including:
00002 // simonbarker on MBED
00003 // The search code is a port of Jim Studt's Adruino One Wire lib
00004 // Can handle multiple devices per pin
00005 // Rob Dobson, 2015
00006 
00007 #include "Onewire.h"
00008 
00009 Onewire::Onewire(PinName oneBus):oneBus_(oneBus)
00010 {    
00011 }
00012 
00013 void Onewire::writeBit(int bit) 
00014 {
00015     __disable_irq();
00016     bit = bit & 0x01;
00017     if (bit) 
00018     {
00019         // Write '1' bit
00020         __disable_irq();
00021         oneBus_.output();
00022         oneBus_ = 0;
00023         wait_us(10);
00024         oneBus_ = 1;
00025         __enable_irq();        
00026         wait_us(55);
00027     }
00028     else
00029     {
00030         // Write '0' bit
00031         __disable_irq();
00032         oneBus_.output();
00033         oneBus_ = 0;
00034         wait_us(65);
00035         oneBus_ = 1;
00036         __enable_irq();        
00037         wait_us(5);
00038     }
00039     __enable_irq();
00040 }
00041 
00042 int Onewire::readBit() 
00043 {
00044     char result;
00045 
00046     __disable_irq();
00047     oneBus_.output();
00048     oneBus_ = 0;
00049     wait_us(3);
00050     oneBus_.input();
00051     wait_us(10);
00052     result = oneBus_.read();
00053     __enable_irq();
00054     wait_us(53);
00055     return result;
00056 }
00057 
00058 int Onewire::init()
00059 {
00060     // Ensure bus is high to start
00061     oneBus_.input();
00062     int MAX_RETRY_TEST_BUS_HIGH = 125;
00063     for (int i = 0; i < MAX_RETRY_TEST_BUS_HIGH; i++)
00064     {
00065         if (oneBus_.read() == 1)
00066             break;
00067         wait_us(2);
00068     }
00069     if (oneBus_.read() != 1)
00070         return ONEWIRE_FAIL_STUCK_LOW;
00071     
00072     // Pull LOW for 480us
00073     __disable_irq();
00074     oneBus_.output();
00075     oneBus_ = 0;
00076     __enable_irq();
00077     wait_us(480);
00078     
00079     // Allow to float and test to ensure presence of devices
00080     // (which pull the bus low)
00081     __disable_irq();
00082     oneBus_.input();
00083     wait_us(70);
00084     int readVal = oneBus_.read();
00085     __enable_irq();
00086     wait_us(410);
00087     return (readVal == 0) ? ONEWIRE_OK : ONEWIRE_SEARCH_INIT_FAIL;
00088 }
00089 
00090 int Onewire::readByte() 
00091 {
00092     int result = 0;
00093 
00094     for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) {
00095         // shift the result to get it ready for the next bit
00096         result >>= 1;
00097 
00098         // if result is one, then set MS bit
00099         if (readBit())
00100             result |= 0x80;
00101     }
00102     return result;
00103 }
00104 
00105 void Onewire::writeByte(char data) 
00106 {
00107     // Loop to write each bit in the byte, LS-bit first
00108     for (int loop = 0; loop < ONEWIRE_ADDR_BYTES; loop++) {
00109         writeBit(data & 0x01);
00110 
00111         // shift the data byte for the next bit
00112         data >>= 1;
00113     }
00114 }
00115 
00116 unsigned char Onewire::CRC(unsigned char* addr, unsigned char len) 
00117 {
00118     unsigned char i, j;
00119     unsigned char crc = 0;
00120 
00121     for (i = 0; i < len; i++) {
00122         unsigned char inbyte = addr[i];
00123         for (j = 0; j < ONEWIRE_ADDR_BYTES; j++) {
00124             unsigned char mix = (crc ^ inbyte) & 0x01;
00125             crc >>= 1;
00126             if (mix) crc ^= 0x8C;
00127             inbyte >>= 1;
00128         }
00129     }
00130     return crc;
00131 }
00132 
00133 //
00134 // You need to use this function to start a search again from the beginning.
00135 // You do not need to do it for the first search, though you could.
00136 //
00137 void Onewire::reset_search()
00138 {
00139     // reset the search state
00140     _search_LastDiscrepancy = 0;
00141     _search_LastDeviceFlag = false;
00142     _search_LastFamilyDiscrepancy = 0;
00143     for(int i = ONEWIRE_ADDR_BYTES-1; i >= 0; i--) 
00144         _search_ROM_NO[i] = 0;
00145 }
00146 
00147 // Search Based on Maxim DS18B20 Algorithm
00148 // https://www.maximintegrated.com/en/app-notes/index.mvp/id/187
00149 //
00150 // Perform a search, returns:
00151 // ONEWIRE_OK if a new address has been returned.
00152 // ONEWIRE_SEARCH_ALL_DONE = all devices found
00153 // ONEWIRE_SEARCH_INIT_FAIL = failed to init
00154 // ONEWIRE_SEARCH_NOT_FOUND = no devices found If this function returns a '1' then it has
00155 // ONEWIRE_SEARCH_STUCK_HIGH = bus is stuck high
00156 // ONEWIRE_SEARCH_COMP_BIT_ERR = complement bit error
00157 //
00158 uint8_t Onewire::search(uint8_t *newAddr)
00159 {
00160     // initialize for search
00161     uint8_t last_zero = 0;
00162     unsigned char search_direction = 0;
00163 
00164     // if the previous call was the last one
00165     if (_search_LastDeviceFlag)
00166         return ONEWIRE_SEARCH_ALL_DONE;
00167         
00168     // 1-Wire reset
00169     int initRslt = init();
00170     if (initRslt != ONEWIRE_OK)
00171     {
00172         // reset the search
00173         reset_search();
00174         return initRslt;
00175     }
00176     
00177     // issue the search command
00178     writeByte(0xF0);
00179     
00180     // loop to do the search
00181     for (int id_bit_number = 1; id_bit_number <= 64; id_bit_number++)
00182     {
00183         // read a bit and its complement
00184         uint8_t id_bit = readBit();
00185         uint8_t cmp_id_bit = readBit();
00186         
00187         // check for no devices on 1-wire
00188         if ((id_bit == 1) && (cmp_id_bit == 1))
00189         {
00190             reset_search();
00191             return ONEWIRE_SEARCH_COMP_BIT_ERR;
00192         }
00193 
00194         // all devices coupled have 0 or 1
00195         int byteNo = (id_bit_number - 1) / 8;
00196         int byteMask = 1 << ((id_bit_number - 1) % 8);
00197         if (id_bit != cmp_id_bit)
00198         {
00199             search_direction = id_bit;  // bit write value for search
00200         }           
00201         else
00202         {
00203             if (id_bit_number == _search_LastDiscrepancy)
00204             {
00205                 search_direction = 1;
00206             }
00207             else if (id_bit_number > _search_LastDiscrepancy)
00208             {
00209                 search_direction = 0;
00210             }
00211             else
00212             {
00213                 search_direction = ((_search_ROM_NO[byteNo] & byteMask) > 0);
00214             }
00215             
00216             // if 0 was picked then record its position in LastZero
00217             if (search_direction == 0)
00218             {
00219                 last_zero = id_bit_number;
00220                 // check for Last discrepancy in family
00221                 if (last_zero < 9)
00222                     _search_LastFamilyDiscrepancy = last_zero;
00223             }
00224         }
00225         
00226         // set or clear the bit in the ROM byte rom_byte_number
00227         // with mask rom_byte_mask
00228         
00229         if (search_direction == 1)
00230             _search_ROM_NO[byteNo] |= byteMask;
00231         else
00232             _search_ROM_NO[byteNo] &= ~byteMask;
00233         
00234         // serial number search direction write bit
00235         writeBit(search_direction);
00236     }
00237     
00238     // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
00239     _search_LastDiscrepancy = last_zero;
00240     // check for last device
00241     if (_search_LastDiscrepancy == 0)
00242         _search_LastDeviceFlag = true;
00243     
00244     // Copy address to return
00245     for (int i = 0; i < ONEWIRE_ADDR_BYTES; i++)
00246         newAddr[i] = _search_ROM_NO[i];
00247         
00248     return ONEWIRE_OK;
00249 }
00250 
00251 char* Onewire::GetErrorStr(int errCode)
00252 {
00253     switch(errCode)
00254     {
00255         case ONEWIRE_OK: return "OK";
00256         case ONEWIRE_FAIL_STUCK_LOW: return "Stuck Low";
00257         case ONEWIRE_SEARCH_ALL_DONE: return "All Done";
00258         case ONEWIRE_SEARCH_INIT_FAIL: return "Init Fail";
00259         case ONEWIRE_SEARCH_NOT_FOUND: return "Not Found";
00260         case ONEWIRE_SEARCH_COMP_BIT_ERR: return "Comp Bit Err";
00261     }
00262     return "Unknown Err";
00263 }
00264