Extended MaximInterface
Dependents: mbed_DS28EC20_GPIO
Diff: Platforms/dotnet/DS9481P_300.cpp
- Revision:
- 0:f77ad7f72d04
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Platforms/dotnet/DS9481P_300.cpp Mon Nov 06 14:39:18 2017 -0600 @@ -0,0 +1,283 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <utility> +#include <msclr/marshal_cppstd.h> +#include <MaximInterface/Utilities/Error.hpp> +#include "DS9481P_300.hpp" + +using System::IO::Ports::SerialPort; +using msclr::interop::marshal_as; +using std::string; + +namespace MaximInterface { + +DS9481P_300::DS9481P_300() + : currentBus(Bus::None), linkLayerMaster("{DS9097U_DS9480}"), + oneWireMaster_(*this), serial(), ds9400(serial), i2cMaster_(*this) {} + +DS9481P_300::~DS9481P_300() { disconnect(); } + +error_code DS9481P_300::connect(const string & portName) { + return connected() ? make_error_code(ConnectionStateError) + : selectBus(Bus::OneWire, portName); +} + +void DS9481P_300::disconnect() { selectBus(Bus::None); } + +string DS9481P_300::portName() const { + switch (currentBus) { + case Bus::I2C: + return serial.portName(); + + case Bus::OneWire: + return linkLayerMaster.portName(); + } + return ""; +} + +error_code DS9481P_300::selectBus(Bus newBus) { + return connected() ? selectBus(newBus, portName()) + : make_error_code(ConnectionStateError); +} + +error_code DS9481P_300::selectBus(Bus newBus, const string & portName) { + error_code result; + if (currentBus != newBus) { + const auto selectI2C = [this](const string & portName) { + auto result = serial.connect(portName); + if (!result) { + // Escape DS2480 Mode. + result = serial.writeByte(0xE5); + } + if (!result) { + // Wait for awake notification. + uint_least8_t data; + result = serial.readByte(data); + } + return result; + }; + + const auto selectOneWire = [this](const string & portName) { + return linkLayerMaster.connect(portName); + }; + + switch (currentBus) { + case Bus::None: + switch (newBus) { + case Bus::OneWire: + result = selectOneWire(portName); + break; + + case Bus::I2C: + result = selectI2C(portName); + break; + } + break; + + case Bus::OneWire: + linkLayerMaster.disconnect(); + switch (newBus) { + case Bus::I2C: + result = selectI2C(portName); + break; + } + break; + + case Bus::I2C: { + constexpr uint_least8_t buffer[] = {'C', 'O'}; + result = serial.writeBlock(buffer, sizeof(buffer) / sizeof(buffer[0])); + if (!result) { + serial.disconnect(); + switch (newBus) { + case Bus::OneWire: + result = selectOneWire(portName); + break; + } + } + } break; + } + if (!result) { + currentBus = newBus; + } + } + return result; +} + +error_code DS9481P_300::OneWireMasterImpl::reset() { + return selectAndExecute([this] { return OneWireMasterDecorator::reset(); }); +} + +error_code DS9481P_300::OneWireMasterImpl::touchBitSetLevel(bool & sendRecvBit, + Level afterLevel) { + return selectAndExecute([this, &sendRecvBit, afterLevel] { + return OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel); + }); +} + +error_code +DS9481P_300::OneWireMasterImpl::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + return selectAndExecute([this, sendByte, afterLevel] { + return OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel); + }); +} + +error_code +DS9481P_300::OneWireMasterImpl::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + return selectAndExecute([this, &recvByte, afterLevel] { + return OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel); + }); +} + +error_code +DS9481P_300::OneWireMasterImpl::writeBlock(const uint_least8_t * sendBuf, + size_t sendLen) { + return selectAndExecute([this, sendBuf, sendLen] { + return OneWireMasterDecorator::writeBlock(sendBuf, sendLen); + }); +} + +error_code DS9481P_300::OneWireMasterImpl::readBlock(uint_least8_t * recvBuf, + size_t recvLen) { + return selectAndExecute([this, recvBuf, recvLen] { + return OneWireMasterDecorator::readBlock(recvBuf, recvLen); + }); +} + +error_code DS9481P_300::OneWireMasterImpl::setSpeed(Speed newSpeed) { + return selectAndExecute( + [this, newSpeed] { return OneWireMasterDecorator::setSpeed(newSpeed); }); +} + +error_code DS9481P_300::OneWireMasterImpl::setLevel(Level newLevel) { + return selectAndExecute( + [this, newLevel] { return OneWireMasterDecorator::setLevel(newLevel); }); +} + +error_code DS9481P_300::OneWireMasterImpl::triplet(TripletData & data) { + return selectAndExecute( + [this, &data] { return OneWireMasterDecorator::triplet(data); }); +} + +template <typename Func> +error_code DS9481P_300::OneWireMasterImpl::selectAndExecute(Func operation) { + auto result = parent->selectBus(Bus::OneWire); + if (!result) { + result = operation(); + } + return result; +} + +error_code DS9481P_300::I2CMasterImpl::start(uint_least8_t address) { + return selectAndExecute( + [this, address] { return I2CMasterDecorator::start(address); }); +} + +error_code DS9481P_300::I2CMasterImpl::stop() { + return selectAndExecute([this] { return I2CMasterDecorator::stop(); }); +} + +error_code DS9481P_300::I2CMasterImpl::writeByte(uint_least8_t data) { + return selectAndExecute( + [this, data] { return I2CMasterDecorator::writeByte(data); }); +} + +error_code DS9481P_300::I2CMasterImpl::writeBlock(const uint_least8_t * data, + size_t dataLen) { + return selectAndExecute([this, data, dataLen] { + return I2CMasterDecorator::writeBlock(data, dataLen); + }); +} + +error_code DS9481P_300::I2CMasterImpl::writePacket(uint_least8_t address, + const uint_least8_t * data, + size_t dataLen, + bool sendStop) { + return selectAndExecute([this, address, data, dataLen, sendStop] { + return I2CMasterDecorator::writePacket(address, data, dataLen, sendStop); + }); +} + +error_code DS9481P_300::I2CMasterImpl::readByte(AckStatus status, + uint_least8_t & data) { + return selectAndExecute([this, status, &data] { + return I2CMasterDecorator::readByte(status, data); + }); +} + +error_code DS9481P_300::I2CMasterImpl::readBlock(AckStatus status, + uint_least8_t * data, + size_t dataLen) { + return selectAndExecute([this, status, data, dataLen] { + return I2CMasterDecorator::readBlock(status, data, dataLen); + }); +} + +error_code DS9481P_300::I2CMasterImpl::readPacket(uint_least8_t address, + uint_least8_t * data, + size_t dataLen, + bool sendStop) { + return selectAndExecute([this, address, data, dataLen, sendStop] { + return I2CMasterDecorator::readPacket(address, data, dataLen, sendStop); + }); +} + +template <typename Func> +error_code DS9481P_300::I2CMasterImpl::selectAndExecute(Func operation) { + auto result = parent->selectBus(Bus::I2C); + if (!result) { + result = operation(); + } + return result; +} + +const error_category & DS9481P_300::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS9481P_300"; } + + virtual std::string message(int condition) const { + switch (condition) { + case ConnectionStateError: + return "Connection State Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterface \ No newline at end of file