Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Platforms/dotnet/DS9481P_300.cpp

Committer:
IanBenzMaxim
Date:
2017-11-06
Revision:
0:f77ad7f72d04

File content as of revision 0:f77ad7f72d04:

/*******************************************************************************
* 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