/*
 * 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_TWISLAVE_CPP
#error "this file cannot be compiled directly"
#endif
#undef INCLUDE_ECXX_PLATFORM_SPECIFIC_AVR_COMMON_TWISLAVE_CPP


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


namespace eCxx {


//
// A simple AVR TWI-slave wrapper
//
void TWISlave::__onRx_internal(const uint8_t* data, uint8_t len)
{
    TWISlave& inst = TWISlave::instance();

    if( !inst._onRx ) return;

    RingBuffer<uint8_t, Application::TWIBufferSize>& buff = Application::twiSlave()._buff;
    buff.clear();

    while(len) {
        buff.put(*data++);
        --len;
        if( buff.full() ) {
            inst._onRx( buff.size() );
            buff.clear();
        }
    }

    if( !buff.empty() ) inst._onRx( buff.size() );
}


void TWISlave::__onTx_internal()
{
    TWISlave& inst = TWISlave::instance();

    if(inst._onTx ) inst._onTx();
}


void TWISlave::begin(uint8_t slaveAddress, RxCallbackF rxcb, TxCallbackF txcb)
{
    _onRx = rxcb;
    _onTx = txcb;

    TWIDriver::instance().begin(slaveAddress, &TWISlave::__onRx_internal, &TWISlave::__onTx_internal, 0);
}


void TWISlave::end()
{
    TWIDriver::instance().end();

    _onRx = nullptr;
    _onTx = nullptr;
}


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


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


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


TWIResultCode TWISlave::write(uint8_t value)
{ return TWIDriver::instance().transmitToMaster(&value, 1); }


TWIResultCode TWISlave::write(const void* data, uint8_t len)
{ return TWIDriver::instance().transmitToMaster(static_cast<const uint8_t*>(data), len); }


} // namespace eCxx
