Maxim Integrated / OneWire

Dependents:   MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS248x.cpp Source File

DS248x.cpp

00001 /******************************************************************//**
00002 * Copyright (C) 2016 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 "Masters/DS248x/DS248x.h"
00034 #include "I2C.h"
00035 
00036 using OneWire::OneWireMaster;
00037 using OneWire::DS248x;
00038 
00039 /// DS248x Status Bits
00040 enum StatusBit
00041 {
00042     Status_1WB = 0x01,
00043     Status_PPD = 0x02,
00044     Status_SD = 0x04,
00045     Status_LL = 0x08,
00046     Status_RST = 0x10,
00047     Status_SBR = 0x20,
00048     Status_TSB = 0x40,
00049     Status_DIR = 0x80
00050 };
00051 
00052 static const int I2C_WRITE_OK = 0;
00053 static const int I2C_READ_OK = 0;
00054 
00055 uint8_t DS248x::Config::readByte() const
00056 {
00057     uint8_t config = 0;
00058     if (get1WS())
00059     {
00060         config |= 0x08;
00061     }
00062     if (getSPU())
00063     {
00064         config |= 0x04;
00065     }
00066     if (getPDN())
00067     {
00068         config |= 0x02;
00069     }
00070     if (getAPU())
00071     {
00072         config |= 0x01;
00073     }
00074     return config;
00075 }
00076 
00077 uint8_t DS248x::Config::writeByte() const
00078 {
00079     uint8_t config = readByte();
00080     return ((~config << 4) | config);
00081 }
00082 
00083 void DS248x::Config::reset()
00084 {
00085     set1WS(false);
00086     setSPU(false);
00087     setPDN(false);
00088     setAPU(true);
00089 }
00090 
00091 
00092 DS248x::DS248x(mbed::I2C & i2c_bus, uint8_t adrs):
00093 m_i2c_bus(i2c_bus), m_adrs(adrs)
00094 {
00095 }
00096 
00097 
00098 OneWireMaster::CmdResult DS248x::OWInitMaster (void)
00099 {
00100     OneWireMaster::CmdResult result;
00101 
00102     // reset DS2465 
00103     result = reset();
00104     if (result != OneWireMaster::Success)
00105     {
00106         return result;
00107     }
00108 
00109     // write the default configuration setup
00110     Config defaultConfig;
00111     result = writeConfig(defaultConfig, true);
00112     return result;
00113 }
00114 
00115 OneWireMaster::CmdResult DS248x::reset(void)
00116 {
00117     // Device Reset
00118     //   S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P
00119     //  [] indicates from slave
00120     //  SS status byte to read to verify state
00121 
00122     OneWireMaster::CmdResult result;
00123     uint8_t buf;
00124 
00125     result = sendCommand (DeviceResetCmd);
00126 
00127     if (result == OneWireMaster::Success)
00128     {
00129         result = readRegister(StatusReg, buf, true);
00130     }
00131 
00132     if (result == OneWireMaster::Success)
00133     {
00134         if ((buf & 0xF7) != 0x10)
00135         {
00136             result = OneWireMaster::OperationFailure;
00137         }
00138     }
00139 
00140     if (result == OneWireMaster::Success)
00141     {
00142         OWReset(); // do a command to get 1-Wire master reset out of holding state
00143     }
00144 
00145     return result;
00146 }
00147 
00148 
00149 OneWireMaster::CmdResult DS248x::OWTriplet (SearchDirection & searchDirection, uint8_t & sbr, uint8_t & tsb)
00150 {
00151     // 1-Wire Triplet (Case B)
00152     //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
00153     //                                         \--------/
00154     //                           Repeat until 1WB bit has changed to 0
00155     //  [] indicates from slave
00156     //  SS indicates byte containing search direction bit value in msbit
00157 
00158     OneWireMaster::CmdResult result;
00159     result = sendCommand (OwTripletCmd, (uint8_t)((searchDirection == WriteOne) ? 0x80 : 0x00));
00160     if (result == OneWireMaster::Success)
00161     {
00162         uint8_t status;
00163         result = pollBusy(&status);
00164         if (result == OneWireMaster::Success)
00165         {
00166             // check bit results in status byte
00167             sbr = ((status & Status_SBR) == Status_SBR);
00168             tsb = ((status & Status_TSB) == Status_TSB);
00169             searchDirection = ((status & Status_DIR) == Status_DIR) ? WriteOne : WriteZero;
00170         }
00171     }
00172     return result;
00173 }
00174 
00175 OneWireMaster::CmdResult DS248x::OWReset()
00176 {
00177     // 1-Wire reset (Case B)
00178     //   S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
00179     //                                   \--------/
00180     //                       Repeat until 1WB bit has changed to 0
00181     //  [] indicates from slave
00182 
00183     OneWireMaster::CmdResult result;
00184     uint8_t buf;
00185 
00186     result = sendCommand (OwResetCmd);
00187 
00188     if (result == OneWireMaster::Success)
00189     {
00190         result = pollBusy(&buf);
00191     }
00192 
00193     if (result == OneWireMaster::Success)
00194     {
00195         // check for presence detect
00196         if ((buf & Status_PPD) != Status_PPD)
00197         {
00198             result = OneWireMaster::OperationFailure;
00199         }
00200     }
00201 
00202     return result;
00203 }
00204 
00205 OneWireMaster::CmdResult DS248x::OWTouchBitSetLevel(uint8_t & sendRecvBit, OWLevel afterLevel)
00206 {
00207     // 1-Wire bit (Case B)
00208     //   S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P
00209     //                                          \--------/
00210     //                           Repeat until 1WB bit has changed to 0
00211     //  [] indicates from slave
00212     //  BB indicates byte containing bit value in msbit
00213 
00214     OneWireMaster::CmdResult result;
00215 
00216     result = configureLevel(afterLevel);
00217     if (result != OneWireMaster::Success)
00218     {
00219         return result;
00220     }
00221 
00222     uint8_t status;
00223 
00224     result = sendCommand (OwSingleBitCmd, (uint8_t)(sendRecvBit ? 0x80 : 0x00));
00225 
00226     if (result == OneWireMaster::Success)
00227     {
00228         result = pollBusy(&status);
00229     }
00230 
00231     if (result == OneWireMaster::Success)
00232     {
00233         sendRecvBit = (status & Status_SBR);
00234     }
00235 
00236     return result;
00237 }
00238 
00239 OneWireMaster::CmdResult DS248x::OWWriteByteSetLevel(uint8_t sendByte, OWLevel afterLevel)
00240 {
00241     // 1-Wire Write Byte (Case B)
00242     //   S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P
00243     //                                          \--------/
00244     //                             Repeat until 1WB bit has changed to 0
00245     //  [] indicates from slave
00246     //  DD data to write
00247 
00248     OneWireMaster::CmdResult result;
00249 
00250     result = configureLevel(afterLevel);
00251     if (result != OneWireMaster::Success)
00252     {
00253         return result;
00254     }
00255 
00256     result = sendCommand (OwWriteByteCmd, sendByte);
00257     if (result == OneWireMaster::Success)
00258     {
00259         result = pollBusy();
00260     }
00261 
00262     return result;
00263 }
00264 
00265 OneWireMaster::CmdResult DS248x::OWReadByteSetLevel(uint8_t & recvByte, OWLevel afterLevel)
00266 {
00267     // 1-Wire Read Bytes (Case C)
00268     //   S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
00269     //                                   \--------/
00270     //                     Repeat until 1WB bit has changed to 0
00271     //   Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
00272     //
00273     //  [] indicates from slave
00274     //  DD data read
00275 
00276     OneWireMaster::CmdResult result;
00277     uint8_t buf;
00278 
00279     result = configureLevel(afterLevel);
00280     if (result != OneWireMaster::Success)
00281     {
00282         return result;
00283     }
00284 
00285     result = sendCommand (OwReadByteCmd);
00286 
00287     if (result == OneWireMaster::Success)
00288     {
00289         result = pollBusy();
00290     }
00291 
00292     if (result == OneWireMaster::Success)
00293     {
00294         result = readRegister(ReadDataReg, buf);
00295     }
00296 
00297     if (result == OneWireMaster::Success)
00298     {
00299         recvByte = buf;
00300     }
00301 
00302     return result;
00303 }
00304 
00305 OneWireMaster::CmdResult DS248x::OWSetSpeed(OWSpeed newSpeed)
00306 {
00307     // Requested speed is already set
00308     if (m_curConfig.get1WS () == (newSpeed == OverdriveSpeed))
00309     {
00310         return OneWireMaster::Success;
00311     }
00312 
00313     // set the speed
00314     Config newConfig = m_curConfig;
00315     newConfig.set1WS(newSpeed == OverdriveSpeed);
00316 
00317     // write the new config
00318     return writeConfig(newConfig, true);
00319 }
00320 
00321 OneWireMaster::CmdResult DS248x::OWSetLevel(OWLevel newLevel)
00322 {
00323     if (newLevel == StrongLevel)
00324     {
00325         return OneWireMaster::OperationFailure;
00326     }
00327 
00328     return configureLevel(newLevel);
00329 }
00330 
00331 OneWireMaster::CmdResult DS248x::writeConfig(const Config & config, bool verify)
00332 {
00333     uint8_t configBuf;
00334     OneWireMaster::CmdResult result;
00335 
00336     configBuf = config.writeByte();
00337     result = sendCommand (WriteDeviceConfigCmd, configBuf);
00338     if (verify)
00339     {
00340         if (result == OneWireMaster::Success)
00341         {
00342             result = readRegister(ConfigReg, configBuf);
00343         }
00344         if (result == OneWireMaster::Success)
00345         {
00346             if (configBuf != config.readByte())
00347             {
00348                 result = OneWireMaster::OperationFailure;
00349             }
00350         }
00351     }
00352 
00353     if (result == OneWireMaster::Success)
00354     {
00355         m_curConfig = config;
00356     }
00357 
00358     return result;
00359 }
00360 
00361 OneWireMaster::CmdResult DS248x::readRegister(Register reg, uint8_t & buf, bool skipSetPointer) const
00362 {
00363     CmdResult result = Success;
00364     if (!skipSetPointer)
00365     {
00366         result = sendCommand (SetReadPointerCmd, reg);
00367     }
00368     if (result == Success)
00369     {
00370         if (m_i2c_bus.read(m_adrs, reinterpret_cast<char *>(&buf), 1) != I2C_READ_OK)
00371         {
00372             result = CommunicationReadError;
00373         }
00374     }
00375     return result;
00376 }
00377 
00378 OneWireMaster::CmdResult DS248x::pollBusy(uint8_t * pStatus)
00379 {
00380     const unsigned int pollLimit = 200;
00381 
00382     OneWireMaster::CmdResult result;
00383     uint8_t status;
00384     unsigned int pollCount = 0;
00385 
00386     do
00387     {
00388         result = readRegister(StatusReg, status, true);
00389         if (result != OneWireMaster::Success)
00390         {
00391             return result;
00392         }
00393         if (pStatus != NULL)
00394         {
00395             *pStatus = status;
00396         }
00397         if (pollCount++ >= pollLimit)
00398         {
00399             return OneWireMaster::TimeoutError;
00400         }
00401     } while (status & Status_1WB);
00402 
00403     return OneWireMaster::Success;
00404 }
00405 
00406 OneWireMaster::CmdResult DS248x::configureLevel(OWLevel level)
00407 {
00408     OneWireMaster::CmdResult result;
00409     if (m_curConfig.getSPU () != (level == StrongLevel))
00410     {
00411         Config newConfig = m_curConfig;
00412         newConfig.setSPU(level == StrongLevel);
00413         result = writeConfig(newConfig, true);
00414     }
00415     else
00416     {
00417         result = OneWireMaster::Success;
00418     }
00419     return result;
00420 }
00421 
00422 OneWireMaster::CmdResult DS248x::sendCommand (Command cmd) const
00423 {
00424     CmdResult result;
00425     if (m_i2c_bus.write(m_adrs, reinterpret_cast<const char *>(&cmd), 1) == I2C_WRITE_OK)
00426     {
00427         result = Success;
00428     }
00429     else
00430     {
00431         result = CommunicationWriteError;
00432     }
00433     return result;
00434 }
00435 
00436 OneWireMaster::CmdResult DS248x::sendCommand (Command cmd, uint8_t param) const
00437 {
00438     CmdResult result;
00439     uint8_t buf[2] = { cmd, param };
00440     if (m_i2c_bus.write(m_adrs, reinterpret_cast<const char *>(buf), 2) == I2C_WRITE_OK)
00441     {
00442         result = Success;
00443     }
00444     else
00445     {
00446         result = CommunicationWriteError;
00447     }
00448     return result;
00449 }