/*
 * Copyright 2018 Matthew Brush <mbrush@codebrainz.ca>
 *
 * 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 THE AUTHORS OR COPYRIGHT HOLDERS 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.
 */
 
 /*
  * Modified to work with SoftwareWire using code from SparkFun BME280 driver
  *
  * Author: pldr
  * Modified: 05/31/2019
  */

#include <INA260.h>

//Begin comm with BME280 over I2C
bool INA260::beginI2C(TwoWire &wirePort) {
	_hardPort = &wirePort;
	_wireType = HARD_WIRE;
	
	return reset();
}

//Begin comm with BME280 over software I2C
#ifdef SoftwareWire_h
bool INA260::beginI2C(SoftwareWire& wirePort) {
	_softPort = &wirePort;
	_wireType = SOFT_WIRE;

    return reset();

}
#endif

bool INA260::readRegister(uint8_t reg, uint16_t &value) const {
  bool retVal = false;
  uint8_t result[2];
  int bytesRead = 0;
  switch(_wireType)
  {
      case (HARD_WIRE):
          _hardPort->beginTransmission(addr);
          _hardPort->write(reg);
          _hardPort->endTransmission();
          _hardPort->requestFrom(addr, 2u);
          if (_hardPort->available() == 2) {
            const uint16_t msb = _hardPort->read();
            const uint16_t lsb = _hardPort->read();
            value = (msb << 8) | lsb;
            retVal = true;
          }
          break;
      case (SOFT_WIRE):
      #ifdef SoftwareWire_h
          _softPort->beginTransmission(addr);
          _softPort->write(reg);
          _softPort->endTransmission();
          _softPort->requestFrom(addr, 2u);
          while (_softPort->available() && bytesRead < 2) // slave may send less than requested
          {
              result[bytesRead++] = _softPort->read(); // receive a byte as a proper uint8_t
              
          }
          
          if (bytesRead == 2) {
            const uint16_t msb = result[0];
            const uint16_t lsb = result[1];
            value = (msb << 8) | lsb;
            retVal = true;
          }
          break;
      #endif
  }
  return retVal;
}

bool INA260::writeRegister(uint8_t reg, uint16_t value) const {

    //Write the byte
    bool retVal = false;

    switch(_wireType)
    {
        case(HARD_WIRE):
            _hardPort->beginTransmission(addr);
            _hardPort->write(reg);
            _hardPort->write((value >> 8) & 0xFF);
            _hardPort->write(value & 0xFF);
            retVal = _hardPort->endTransmission() == 0;
            break;
        case(SOFT_WIRE):
        #ifdef SoftwareWire_h
            _softPort->beginTransmission(addr);
            _softPort->write(reg);
            _softPort->write((value >> 8) & 0xFF);
            _softPort->write(value & 0xFF);
            retVal = _softPort->endTransmission() == 0;
        #endif
            break;
    }
    return retVal;

}
