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

#include <math.h>

#include "bcdtodec.h"
#include "itemlibrary.h"
#include "circuit.h"
#include "iopin.h"

#include "boolprop.h"

#define tr(str) simulideTr("BcdToDec",str)

Component* BcdToDec::construct( QString type, QString id )
{ return new BcdToDec( type, id ); }

LibraryItem* BcdToDec::libraryItem()
{
    return new LibraryItem(
        tr("Decoder(4 to 10/16)"),
        "Converters",
        "2to3g.png",
        "BcdToDec",
        BcdToDec::construct );
}

BcdToDec::BcdToDec( QString type, QString id )
        : LogicComponent( type, id )
{
    m_width  = 4;
    m_height = 11;

    m_tristate = true;
    m_16Bits   = false;

    setNumInps( 4,"S" );
    setNumOuts( 10 );
    createOePin( "IU01OE ", id+"-in4"); // Output Enable

    addPropGroup( { tr("Main"), {
        new BoolProp<BcdToDec>("_16_Bits", tr("16 Bits"),""
                              , this, &BcdToDec::is16Bits, &BcdToDec::set_16bits, propNoCopy ),
    },groupNoCopy} );

    appendPropGroup( tr("Main"), IoComponent::familyProps() );

    addPropGroup( { tr("Inputs")
        , IoComponent::inputProps()
        + QList<ComProperty*>({
            new BoolProp<BcdToDec>("Invert_Inputs", tr("Invert Inputs"),""
                                  , this, &BcdToDec::invertInps, &BcdToDec::setInvertInps, propNoCopy )})
    ,0 } );

    addPropGroup( { tr("Outputs")
    , IoComponent::outputProps()
        + IoComponent::outputType()
        + QList<ComProperty*>({
            new BoolProp<BcdToDec>("Tristate", tr("Tristate"),""
                                  , this, &BcdToDec::tristate, &BcdToDec::setTristate ),
        })
    ,0 } );

    addPropGroup( { tr("Timing"), IoComponent::edgeProps(),0 } );
}
BcdToDec::~BcdToDec(){}

void BcdToDec::stamp()
{
    for( int i=0; i<4; ++i ) m_inpPin[i]->changeCallBack( this );
    LogicComponent::stamp();

    m_outPin[0]->setOutState( true );
    m_outValue = 1;
}

void BcdToDec::voltChanged()
{
    if( m_tristate ) LogicComponent::updateOutEnabled();

    int dec = 0;
    for( int i=0; i<4; ++i )
        if( m_inpPin[i]->getInpState() ) dec += pow( 2, i );

    m_nextOutVal = 1<<dec;
    scheduleOutPuts( this );
}

void BcdToDec::set_16bits( bool set )
{
    m_16Bits = set;
    setNumOuts( m_16Bits ? 16 : 10 );
    m_oePin->setY( m_area.y()-8 );
}
