Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS18B20.cpp Source File

DS18B20.cpp

00001 /*******************************************************************************
00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #include <MaximInterfaceCore/Error.hpp>
00034 #include <MaximInterfaceCore/OneWireMaster.hpp>
00035 #include "DS18B20.hpp"
00036 
00037 #define TRY MaximInterfaceCore_TRY
00038 #define TRY_VALUE MaximInterfaceCore_TRY_VALUE
00039 
00040 namespace MaximInterfaceDevices {
00041 
00042 using namespace Core;
00043 
00044 const uint_least8_t DS18B20::nineBitResolution;
00045 const uint_least8_t DS18B20::tenBitResolution;
00046 const uint_least8_t DS18B20::elevenBitResolution;
00047 const uint_least8_t DS18B20::twelveBitResolution;
00048 
00049 Result<void> DS18B20::initialize() const {
00050   TRY(readScratchpad());
00051   return none;
00052 }
00053 
00054 Result<void> DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl,
00055                                       uint_least8_t res) {
00056   Result<void> result = selectRom(*master);
00057   if (result) {
00058     const uint_least8_t sendBlock[] = {0x4E, th, tl, res};
00059     result = master->writeBlock(sendBlock);
00060     if (result) {
00061       resolution = res;
00062     }
00063   }
00064   return result;
00065 }
00066 
00067 Result<DS18B20::Scratchpad> DS18B20::readScratchpad() const {
00068   Result<void> result = selectRom(*master);
00069   if (!result) {
00070     return result.error();
00071   }
00072   result = master->writeByte(0xBE);
00073   if (!result) {
00074     return result.error();
00075   }
00076   Scratchpad scratchpad;
00077   result = master->readBlock(scratchpad);
00078   if (!result) {
00079     return result.error();
00080   }
00081   uint_least8_t receivedCrc;
00082   TRY_VALUE(receivedCrc, master->readByte());
00083   if (receivedCrc != calculateCrc8(scratchpad)) {
00084     return CrcError;
00085   }
00086   resolution = scratchpad[4];
00087   return scratchpad;
00088 }
00089 
00090 Result<bool> DS18B20::readPowerSupply() const {
00091   Result<void> result = selectRom(*master);
00092   if (!result) {
00093     return result.error();
00094   }
00095   result = master->writeByte(0xB4);
00096   if (!result) {
00097     return result.error();
00098   }
00099   return master->readBit();
00100 }
00101 
00102 Result<void> DS18B20::copyScratchpad() {
00103   const uint_least8_t copyScratchpadCmd = 0x48;
00104 
00105   bool hasLocalPower;
00106   TRY_VALUE(hasLocalPower, readPowerSupply());
00107   Result<void> result = selectRom(*master);
00108   if (!result) {
00109     return result;
00110   }
00111   if (hasLocalPower) {
00112     result = master->writeByte(copyScratchpadCmd);
00113     if (result) {
00114       bool recvBit;
00115       do {
00116         TRY_VALUE(recvBit, master->readBit());
00117       } while (!recvBit);
00118     }
00119   } else {
00120     result = master->writeByteSetLevel(copyScratchpadCmd,
00121                                        OneWireMaster::StrongLevel);
00122     if (result) {
00123       sleep->invoke(10);
00124       result = master->setLevel(OneWireMaster::NormalLevel);
00125     }
00126   }
00127   return result;
00128 }
00129 
00130 Result<void> DS18B20::convertTemperature() {
00131   const uint_least8_t convertTemperatureCmd = 0x44;
00132 
00133   bool hasLocalPower;
00134   TRY_VALUE(hasLocalPower, readPowerSupply());
00135   Result<void> result = selectRom(*master);
00136   if (!result) {
00137     return result;
00138   }
00139   if (hasLocalPower) {
00140     result = master->writeByte(convertTemperatureCmd);
00141     if (result) {
00142       bool recvBit;
00143       do {
00144         TRY_VALUE(recvBit, master->readBit());
00145       } while (!recvBit);
00146     }
00147   } else {
00148     result = master->writeByteSetLevel(convertTemperatureCmd,
00149                                        OneWireMaster::StrongLevel);
00150     if (result) {
00151       int sleepTime;
00152       switch (resolution) {
00153       case nineBitResolution:
00154         sleepTime = 94;
00155         break;
00156 
00157       case tenBitResolution:
00158         sleepTime = 188;
00159         break;
00160 
00161       case elevenBitResolution:
00162         sleepTime = 375;
00163         break;
00164 
00165       case twelveBitResolution:
00166       default:
00167         sleepTime = 750;
00168         break;
00169       }
00170       sleep->invoke(sleepTime);
00171       result = master->setLevel(OneWireMaster::NormalLevel);
00172     }
00173   }
00174   return result;
00175 }
00176 
00177 Result<void> DS18B20::recallEeprom() {
00178   Result<void> result = selectRom(*master);
00179   if (result) {
00180     result = master->writeByte(0xB8);
00181   }
00182   return result;
00183 }
00184 
00185 const error_category & DS18B20::errorCategory() {
00186   static class : public error_category {
00187   public:
00188     virtual const char * name() const {
00189       return "MaximInterfaceDevices.DS18B20";
00190     }
00191 
00192     virtual std::string message(int condition) const {
00193       switch (condition) {
00194       case CrcError:
00195         return "CRC Error";
00196 
00197       case DataError:
00198         return "Data Error";
00199       }
00200       return defaultErrorMessage(condition);
00201     }
00202   } instance;
00203   return instance;
00204 }
00205 
00206 Result<int> readTemperature(DS18B20 & ds18b20) {
00207   TRY(ds18b20.convertTemperature());
00208   DS18B20::Scratchpad scratchpad;
00209   TRY_VALUE(scratchpad, ds18b20.readScratchpad());
00210 
00211   const unsigned int tempData =
00212       (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0];
00213   const unsigned int signMask = 0xF800;
00214   int temperature;
00215   if ((tempData & signMask) == signMask) {
00216     temperature = -0x800;
00217   } else if ((tempData & signMask) == 0) {
00218     temperature = 0;
00219   } else {
00220     return DS18B20::DataError;
00221   }
00222   unsigned int precisionMask;
00223   switch (scratchpad[4]) {
00224   case DS18B20::nineBitResolution:
00225   default:
00226     precisionMask = 0x7;
00227     break;
00228 
00229   case DS18B20::tenBitResolution:
00230     precisionMask = 0x3;
00231     break;
00232 
00233   case DS18B20::elevenBitResolution:
00234     precisionMask = 0x1;
00235     break;
00236 
00237   case DS18B20::twelveBitResolution:
00238     precisionMask = 0x0;
00239     break;
00240   }
00241   temperature += static_cast<int>(tempData & ~(signMask | precisionMask));
00242   return temperature;
00243 }
00244 
00245 } // namespace MaximInterfaceDevices