/***************************************************************************
 *   Copyright (C) 2023 by Santiago González                               *
 *                                                                         *
 ***( see copyright.txt file at root folder )*******************************/

//#include <QDebug>

#include "scripttwi.h"
#include "scriptcpu.h"
#include "angelscript.h"

ScriptTwi::ScriptTwi( eMcu* mcu, QString name )
         : McuTwi( mcu, name )
         , ScriptPerif( name )
{
    m_byteReceived = nullptr; 
    m_writeByte    = nullptr; 

    m_type = "TWI"; 

    m_methods << "setMode( int mode )"
              << "sendByte( uint8 byte )"
              << "setAddress( uint8 address )"; 
}
ScriptTwi::~ScriptTwi(){}

QStringList ScriptTwi::registerScript( ScriptCpu* cpu )
{
    m_scriptCpu = cpu; 

    asIScriptEngine* engine = cpu->engine(); 

    string twi = "TWI "+m_perifName.toStdString(); 
    engine->RegisterObjectType("TWI", 0, asOBJ_REF | asOBJ_NOCOUNT ); 

    engine->RegisterGlobalProperty( twi.c_str(), this ); 

    engine->RegisterObjectMethod("TWI", "void setMode(int t)"
                                   , asMETHODPR( ScriptTwi, setMode, (twiMode_t), void)
                                   , asCALL_THISCALL ); 

    engine->RegisterObjectMethod("TWI", "void sendByte(uint8 b)"
                                   , asMETHODPR( ScriptTwi, sendByte, (uint8_t), void)
                                   , asCALL_THISCALL ); 

    engine->RegisterObjectMethod("TWI", "void setAddress(uint8 a)"
                                   , asMETHODPR( ScriptTwi, setAddress, (uint8_t), void)
                                   , asCALL_THISCALL ); 

    return m_methods; 
}

void ScriptTwi::startScript()
{
    asIScriptEngine* aEngine = m_scriptCpu->engine(); 
    m_byteReceived = aEngine->GetModule(0)->GetFunctionByDecl("void byteReceived( uint d )"); 
    m_writeByte    = aEngine->GetModule(0)->GetFunctionByDecl("uint slaveWrite()"); 
}

void ScriptTwi::reset()
{
}

void ScriptTwi::setAddress( uint8_t a )
{
    m_cCode = m_address = a; 
}

void ScriptTwi::readByte()
{
    if( !m_byteReceived ) return; 

    m_scriptCpu->prepare( m_byteReceived ); 
    m_scriptCpu->context()->SetArgDWord( 0, m_rxReg ); 
    m_scriptCpu->execute(); 

    TwiModule::readByte(); 
}

void ScriptTwi::writeByte() // Master is reading, we send byte m_txReg
{
    TwiModule::writeByte(); 
    if( !m_writeByte ) { m_txReg = 0;  return;  }

    m_scriptCpu->prepare( m_writeByte ); 
    m_scriptCpu->execute(); 
    m_txReg = m_scriptCpu->context()->GetReturnDWord(); 
}

void ScriptTwi::sendByte( uint8_t data )
{
    if( m_mode == TWI_SLAVE ) m_txReg = data; 
    if( m_mode != TWI_MASTER ) return; 

    bool write = false; 
    bool isAddr = (getStaus() == TWI_START
                || getStaus() == TWI_REP_START);  // We just sent Start, so this must be slave address

    if( isAddr ) write = (data & 1) == 0;         // Sending address for Read or Write?

    masterWrite( data, isAddr, write );          /// Write data or address to Slave
}
