Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RunCommand.cpp Source File

RunCommand.cpp

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