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 DS28E17.cpp Source File

DS28E17.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 <stddef.h>
00034 #include <MaximInterfaceCore/Crc.hpp>
00035 #include <MaximInterfaceCore/Error.hpp>
00036 #include <MaximInterfaceCore/OneWireMaster.hpp>
00037 #include "DS28E17.hpp"
00038 
00039 #define TRY MaximInterfaceCore_TRY
00040 #define TRY_VALUE MaximInterfaceCore_TRY_VALUE
00041 
00042 namespace MaximInterfaceDevices {
00043 
00044 using namespace Core;
00045 
00046 Result<void> DS28E17::writeDataWithStop(uint_least8_t I2C_addr,
00047                                         span<const uint_least8_t> data) {
00048   return sendPacket(WriteDataWithStopCmd, &I2C_addr, data,
00049                     span<uint_least8_t>());
00050 }
00051 
00052 Result<void> DS28E17::writeDataNoStop(uint_least8_t I2C_addr,
00053                                       span<const uint_least8_t> data) {
00054   return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>());
00055 }
00056 
00057 Result<void> DS28E17::writeDataOnly(span<const uint_least8_t> data) {
00058   return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>());
00059 }
00060 
00061 Result<void> DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data) {
00062   return sendPacket(WriteDataOnlyWithStopCmd, NULL, data,
00063                     span<uint_least8_t>());
00064 }
00065 
00066 Result<void>
00067 DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr,
00068                                span<const uint_least8_t> write_data,
00069                                span<uint_least8_t> read_data) {
00070   return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data);
00071 }
00072 
00073 Result<void> DS28E17::readDataWithStop(uint_least8_t I2C_addr,
00074                                        span<uint_least8_t> data) {
00075   return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(),
00076                     data);
00077 }
00078 
00079 Result<void> DS28E17::writeConfigReg(I2CSpeed speed) {
00080   Result<void> result = selectRom(*master);
00081   if (result) {
00082     // Send CMD and Data
00083     const uint_least8_t send_block[] = {WriteConfigurationCmd,
00084                                         static_cast<uint_least8_t>(speed)};
00085     result = master->writeBlock(send_block);
00086   }
00087   return result;
00088 }
00089 
00090 Result<DS28E17::I2CSpeed> DS28E17::readConfigReg() const {
00091   TRY(selectRom(*master));
00092   // Send CMD and receive Data
00093   TRY(master->writeByte(ReadConfigurationCmd));
00094   uint_least8_t config;
00095   TRY_VALUE(config, master->readByte());
00096   switch (config) {
00097   case Speed100kHz:
00098   case Speed400kHz:
00099   case Speed900kHz:
00100     return static_cast<I2CSpeed>(config);
00101   }
00102   return OutOfRangeError;
00103 }
00104 
00105 Result<void> DS28E17::enableSleepMode() {
00106   Result<void> result = selectRom(*master);
00107   if (result) {
00108     // Send CMD
00109     result = master->writeByte(EnableSleepModeCmd);
00110   }
00111   return result;
00112 }
00113 
00114 Result<uint_least8_t> DS28E17::readDeviceRevision() const {
00115   Result<void> result = selectRom(*master);
00116   if (!result) {
00117     return result.error();
00118   }
00119   result = master->writeByte(ReadDeviceRevisionCmd);
00120   if (!result) {
00121     return result.error();
00122   }
00123   return master->readByte();
00124 }
00125 
00126 Result<void> DS28E17::sendPacket(Command command,
00127                                  const uint_least8_t * I2C_addr,
00128                                  span<const uint_least8_t> write_data,
00129                                  span<uint_least8_t> read_data) {
00130   const int pollLimit = 10000;
00131   const span<const uint_least8_t>::index_type maxDataLen = 255;
00132 
00133   if ((!write_data.empty() && write_data.size() > maxDataLen) ||
00134       (!read_data.empty() && read_data.size() > maxDataLen)) {
00135     return OutOfRangeError;
00136   }
00137 
00138   Result<void> result = selectRom(*master);
00139   if (!result) {
00140     return result;
00141   }
00142   uint_fast16_t crc16 = calculateCrc16(command);
00143   result = master->writeByte(command);
00144   if (!result) {
00145     return result;
00146   }
00147   if (I2C_addr) {
00148     crc16 = calculateCrc16(crc16, *I2C_addr);
00149     result = master->writeByte(*I2C_addr);
00150     if (!result) {
00151       return result;
00152     }
00153   }
00154   if (!write_data.empty()) {
00155     crc16 = calculateCrc16(crc16, static_cast<uint_fast8_t>(write_data.size()));
00156     result = master->writeByte(static_cast<uint_least8_t>(write_data.size()));
00157     if (!result) {
00158       return result;
00159     }
00160     crc16 = calculateCrc16(crc16, write_data);
00161     result = master->writeBlock(write_data);
00162     if (!result) {
00163       return result;
00164     }
00165   }
00166   if (!read_data.empty()) {
00167     crc16 = calculateCrc16(crc16, static_cast<uint_fast8_t>(read_data.size()));
00168     result = master->writeByte(static_cast<uint_least8_t>(read_data.size()));
00169     if (!result) {
00170       return result;
00171     }
00172   }
00173   crc16 ^= 0xFFFF;
00174   const uint_least8_t crc16Bytes[] = {static_cast<uint_least8_t>(crc16),
00175                                       static_cast<uint_least8_t>(crc16 >> 8)};
00176   result = master->writeBlock(crc16Bytes);
00177   if (!result) {
00178     return result;
00179   }
00180   // Poll for Zero 1-Wire bit and return if an error occurs
00181   int poll_count = 0;
00182   bool recvBit;
00183   do {
00184     if (poll_count++ < pollLimit) {
00185       return TimeoutError;
00186     }
00187     TRY_VALUE(recvBit, master->readBit());
00188   } while (recvBit);
00189   uint_least8_t status;
00190   TRY_VALUE(status, master->readByte());
00191   if ((status & 0x1) == 0x1) {
00192     return InvalidCrc16Error;
00193   }
00194   if ((status & 0x2) == 0x2) {
00195     return AddressNackError;
00196   }
00197   if ((status & 0x8) == 0x8) {
00198     return InvalidStartError;
00199   }
00200   if (!write_data.empty()) {
00201     TRY_VALUE(status, master->readByte());
00202     if (status != 0) {
00203       return error_code(status, errorCategory());
00204     }
00205   }
00206   if (!read_data.empty()) {
00207     result = master->readBlock(read_data);
00208   }
00209   return result;
00210 }
00211 
00212 const error_category & DS28E17::errorCategory() {
00213   static class : public error_category {
00214   public:
00215     virtual const char * name() const {
00216       return "MaximInterfaceDevices.DS28E17";
00217     }
00218 
00219     virtual std::string message(int condition) const {
00220       switch (condition) {
00221       case TimeoutError:
00222         return "Timeout Error";
00223 
00224       case OutOfRangeError:
00225         return "Out of Range Error";
00226 
00227       case InvalidCrc16Error:
00228         return "Invalid CRC16 Error";
00229 
00230       case AddressNackError:
00231         return "Address Nack Error";
00232 
00233       case InvalidStartError:
00234         return "Invalid Start Error";
00235       }
00236       if (condition >= 1 && condition <= 255) {
00237         return "Write Nack Error";
00238       }
00239       return defaultErrorMessage(condition);
00240     }
00241   } instance;
00242   return instance;
00243 }
00244 
00245 } // namespace MaximInterfaceDevices