/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef INCLUDE_ECXX_PLATFORM_SPECIFIC_AVR_COMMON_TWIMASTER_CPP
#error "this file cannot be compiled directly"
#endif
#undef INCLUDE_ECXX_PLATFORM_SPECIFIC_AVR_COMMON_TWIMASTER_CPP


#ifndef __AVR_ARCH_X__
    #include "../AVR/TWIDriver.h"
#else
    #include "../AVRX/TWIDriver.h"
#endif


namespace eCxx {


//
// A simple AVR TWI-master wrapper
//
void TWIMaster::begin(uint32_t frequency)
{ TWIDriver::instance().begin(0, nullptr, nullptr, frequency); }


void TWIMaster::end()
{ TWIDriver::instance().end(); }


void TWIMaster::beginTransmission(uint8_t slaveAddress)
{
    _slaveAddress = slaveAddress;
    _buff.clear();
}


bool TWIMaster::write(uint8_t value)
{ return _buff.put(value); }


bool TWIMaster::write(const void* data_, uint8_t len)
{
    // Cast the buffer for convenience
    const uint8_t* data = static_cast<const uint8_t*>(data_);

    // Check if the buffer will fit
    if(_buff.capacity() < _buff.size() + len) return false;

    // Put the data to the buffer
    for(uint8_t i = 0; i < len; ++i) _buff.put(*data++);

    return true;
}


TWIMaster::TWIResultCode TWIMaster::endTransmission()
{ return TWIDriver::instance().writeTo(_slaveAddress, _buff.data(), _buff.size(), true, true); }


uint8_t TWIMaster::requestFrom(uint8_t slaveAddress, uint8_t len)
{
    // NOTE : This function currently does not support sending internal address for accessing registers!

    // Ensure the buffer will fit
    if(len > _buff.capacity()) len = _buff.capacity();

    // Read from slave
    const uint8_t got = TWIDriver::instance().readFrom(slaveAddress, _buff._writeableData(), len, true);

    // Set and return the read size
    _buff._setWrittenDataSize(got);

    return got;
}


bool TWIMaster::canRead() const
{ return !_buff.empty(); }


bool TWIMaster::read(uint8_t& value)
{ return _buff.get(value); }


bool TWIMaster::peek(uint8_t& value) const
{ return _buff.peek(value); }


} // namespace eCxx
