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

RunCommand.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 "Crc.hpp"
00034 #include "Error.hpp"
00035 #include "I2CMaster.hpp"
00036 #include "OneWireMaster.hpp"
00037 #include "RunCommand.hpp"
00038 #include "Sleep.hpp"
00039 
00040 namespace MaximInterfaceCore {
00041 
00042 const error_category & RunCommandWithOneWireMaster::errorCategory() {
00043   static class : public error_category {
00044   public:
00045     virtual const char * name() const {
00046       return "MaximInterfaceCore.RunCommandWithOneWireMaster";
00047     }
00048 
00049     virtual std::string message(int condition) const {
00050       switch (condition) {
00051       case CrcError:
00052         return "CRC Error";
00053 
00054       case InvalidResponseError:
00055         return "Invalid Response Error";
00056       }
00057       return defaultErrorMessage(condition);
00058     }
00059   } instance;
00060   return instance;
00061 }
00062 
00063 Result<span<uint_least8_t> > RunCommandWithOneWireMaster::
00064 operator()(span<const uint_least8_t> request, int delayTime,
00065            span<uint_least8_t> response) const {
00066   // Write request.
00067   Result<void> result = selectRom(*master);
00068   if (!result) {
00069     return result.error();
00070   }
00071   uint_least8_t xpcBuffer[2] = {0x66,
00072                                 static_cast<uint_least8_t>(request.size())};
00073   result = master->writeBlock(xpcBuffer);
00074   if (!result) {
00075     return result.error();
00076   }
00077   result = master->writeBlock(request);
00078   if (!result) {
00079     return result.error();
00080   }
00081   uint_fast16_t expectedCrc =
00082       calculateCrc16(calculateCrc16(xpcBuffer), request) ^ 0xFFFF;
00083   result = master->readBlock(xpcBuffer);
00084   if (!result) {
00085     return result.error();
00086   }
00087   if (expectedCrc !=
00088       ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
00089     return CrcError;
00090   }
00091   result = master->writeBytePower(0xAA);
00092   if (!result) {
00093     return result.error();
00094   }
00095 
00096   // Wait for device to process.
00097   sleep->invoke(delayTime);
00098 
00099   // Read response.
00100   result = master->setLevel(OneWireMaster::NormalLevel);
00101   if (!result) {
00102     return result.error();
00103   }
00104   result = master->readBlock(xpcBuffer);
00105   if (!result) {
00106     return result.error();
00107   }
00108   if (xpcBuffer[1] > response.size()) {
00109     return InvalidResponseError;
00110   }
00111   response = response.first(xpcBuffer[1]);
00112   result = master->readBlock(response);
00113   if (!result) {
00114     return result.error();
00115   }
00116   expectedCrc =
00117       calculateCrc16(calculateCrc16(make_span(xpcBuffer + 1, 1)), response) ^
00118       0xFFFF;
00119   result = master->readBlock(xpcBuffer);
00120   if (!result) {
00121     return result.error();
00122   }
00123   if (expectedCrc !=
00124       ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
00125     return CrcError;
00126   }
00127   return response;
00128 }
00129 
00130 const error_category & RunCommandWithI2CMaster::errorCategory() {
00131   static class : public error_category {
00132   public:
00133     virtual const char * name() const {
00134       return "MaximInterfaceCore.RunCommandWithI2CMaster";
00135     }
00136 
00137     virtual std::string message(int condition) const {
00138       switch (condition) {
00139       case InvalidResponseError:
00140         return "Invalid Response Error";
00141       }
00142       return defaultErrorMessage(condition);
00143     }
00144   } instance;
00145   return instance;
00146 }
00147 
00148 Result<span<uint_least8_t> > RunCommandWithI2CMaster::
00149 operator()(span<const uint_least8_t> request, int delayTime,
00150            span<uint_least8_t> response) const {
00151   // Write request.
00152   Result<void> result = master->start(address_);
00153   if (!result && result.error() == make_error_condition(I2CMaster::NackError) &&
00154       address_ != 0) {
00155     result = master->start(0);
00156   }
00157   if (!result) {
00158     master->stop();
00159     return result.error();
00160   }
00161   if (!request.empty()) {
00162     result = master->writeByte(request[0]);
00163     if (!result) {
00164       master->stop();
00165       return result.error();
00166     }
00167     request = request.subspan(1);
00168     if (!request.empty()) {
00169       result = master->writeByte(static_cast<uint_least8_t>(request.size()));
00170       if (!result) {
00171         master->stop();
00172         return result.error();
00173       }
00174       result = master->writeBlock(request);
00175       if (!result) {
00176         master->stop();
00177         return result.error();
00178       }
00179     }
00180   }
00181   result = master->stop();
00182   if (!result) {
00183     return result.error();
00184   }
00185 
00186   // Wait for device to process.
00187   sleep->invoke(delayTime);
00188 
00189   // Read response.
00190   result = master->start(address_ | 1);
00191   if (!result) {
00192     master->stop();
00193     return result.error();
00194   }
00195   uint_least8_t length;
00196   if (const Result<uint_least8_t> result = master->readByte(I2CMaster::Ack)) {
00197     length = result.value();
00198   } else {
00199     master->stop();
00200     return result.error();
00201   }
00202   if (length > response.size()) {
00203     master->stop();
00204     return InvalidResponseError;
00205   }
00206   response = response.first(length);
00207   result = master->readBlock(response, I2CMaster::Nack);
00208   if (!result) {
00209     master->stop();
00210     return result.error();
00211   }
00212   result = master->stop();
00213   if (!result) {
00214     return result.error();
00215   }
00216   return response;
00217 }
00218 
00219 } // namespace MaximInterfaceCore