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

#include "scriptusart.h"
#include "scriptcpu.h"
#include "angelscript.h"
#include "usarttx.h"
#include "usartrx.h"
#include "e_mcu.h"

#define SCON *m_scon

ScriptUsart::ScriptUsart( eMcu* mcu, QString name, int number )
           : McuUsart( mcu, name, number )
           , ScriptPerif( name )
{
    m_name = name; 

    m_byteReceived = nullptr; 
    m_frameSent = nullptr; 

    m_type = "Uart"; 

    m_methods << "setBaudRate( int bauds )"
              << "setDataBits( uint8 bits )"
              << "sendByte( uint8 byte )"
                 ; 
}
ScriptUsart::~ScriptUsart(){}

void ScriptUsart::reset()
{
    m_sender->enable( true ); 
    m_receiver->enable( true ); 
}

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

    string uart = "Uart "+m_perifName.toStdString();  // Type name
    asIScriptEngine* engine = cpu->engine(); 

    engine->RegisterObjectType("Uart", 0, asOBJ_REF | asOBJ_NOCOUNT ); 

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

    engine->RegisterObjectMethod("Uart", "void setBaudRate(int t)"
                                   , asMETHODPR( ScriptUsart, setBaudRate, (int), void)
                                   , asCALL_THISCALL ); 

    engine->RegisterObjectMethod("Uart", "void setDataBits(uint8 b)"
                                   , asMETHODPR( ScriptUsart, setDataBits, (int), void)
                                   , asCALL_THISCALL ); 

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

    return m_methods; 
}

void ScriptUsart::startScript()
{
    asIScriptEngine* aEngine = m_scriptCpu->engine(); 
    m_byteReceived = aEngine->GetModule(0)->GetFunctionByDecl("void byteReceived( uint d )"); 
    m_frameSent    = aEngine->GetModule(0)->GetFunctionByDecl("void frameSent( uint data )"); 
}

void ScriptUsart::byteReceived( uint8_t data )
{
    if( !m_byteReceived ) return; 

    data = m_receiver->getData(); 
    m_scriptCpu->prepare( m_byteReceived ); 
    m_scriptCpu->context()->SetArgDWord( 0, data ); 
    m_scriptCpu->execute(); 
}

void ScriptUsart::frameSent( uint8_t data )
{
    if( !m_frameSent ) return; 

    m_scriptCpu->prepare( m_frameSent ); 
    m_scriptCpu->context()->SetArgDWord( 0, data ); 
    m_scriptCpu->execute(); 
}
