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

#include "picvref.h"
#include "datautils.h"
#include "e_mcu.h"
#include "mcupin.h"

PicVref::PicVref( eMcu* mcu, QString name )
       : McuVref( mcu, name )
{
}
PicVref::~PicVref(){}

void PicVref::setup()
{
    m_VREN = getRegBits("VREN", m_mcu ); 
    m_VROE = getRegBits("VROE", m_mcu ); 
    m_VRR  = getRegBits("VRR" , m_mcu ); 
    m_VR   = getRegBits("VR0,VR1,VR2,VR3", m_mcu ); 
}

void PicVref::initialize()
{
    m_vref = m_mcu->vdd()/4;  //setMode( 0 ); 
}

void PicVref::configureA( uint8_t newVRCON )
{
    m_enabled = getRegBitsBool( newVRCON, m_VREN ); 

    bool     vrr = getRegBitsBool( newVRCON, m_VRR ); 
    uint8_t mode = getRegBitsVal( newVRCON, m_VR ); 
    if( mode != m_mode || vrr != m_vrr )
    {
        m_mode = mode; 
        m_vrr = vrr; 

        if( m_enabled ){
            double vdd = m_mcu->vdd(); 
            if( vrr ) m_vref = vdd*mode/24;  /// TODO: get Vdd or use VrefP
            else      m_vref = vdd/4+vdd*mode/32; 
        }
        else m_vref = 0; 
    }
    bool vroe = getRegBitsBool( newVRCON, m_VROE ); 
    m_vroe = vroe; 
    if( m_pinOut )     /// TODO: Add VrefP/VrefN option to ladder
    {
        // VDD-┬-8R-R-..16 Stages..-R-8R-┬-GND
        // VrP-┘                     -VRR┴-VrN
        double vddAdmit = 0; 
        double gndAdmit = 0; 

        if( vroe && m_enabled )
        {
            double vddResist = 0; 
            double gndResist = 0; 
            float R = 2e3; 
            vddResist = R*(8+16-m_mode); 
            if( vrr ) gndResist = vrr ? 1e-3 : 8; 
            gndResist += m_mode; 
            gndResist *= R; 
            if( vddResist ) vddAdmit = 1/vddResist; 
            if( gndResist ) gndAdmit = 1/gndResist; 
        }
        m_pinOut->setExtraSource( vddAdmit, gndAdmit ); 
    }
    if( !m_callBacks.isEmpty() )
    { for( McuModule* mod : m_callBacks ) mod->callBackDoub( m_vref );  }
}

/*void PicVref::setMode( uint8_t mode )
{
    m_mode = mode; 
}*/

//-------------------------------------------------------------
// Type 0: 16f1826 FVR  ---------------------------------------

PicVrefE::PicVrefE( eMcu* mcu, QString name )
        : McuVref( mcu, name )
{
}
PicVrefE::~PicVrefE(){}

void PicVrefE::setup()
{
    m_FVREN  = getRegBits("FVREN", m_mcu ); 
    m_ADFVR  = getRegBits("ADFVR0,ADFVR1", m_mcu );    // ADC Vref
    m_CDAFVR = getRegBits("CDAFVR0,CDAFVR1", m_mcu );  // DAC Vref
}

void PicVrefE::configureA( uint8_t newFVRCON )
{
    m_enabled = getRegBitsVal( newFVRCON, m_FVREN ); 

    double vdd = m_mcu->vdd(); 
    uint8_t adfvr = getRegBitsVal( newFVRCON, m_ADFVR ); 
    switch( adfvr ) {
        case 0: m_adcVref = 0.000;  break; 
        case 1: m_adcVref = 1.024;  break; 
        case 2: m_adcVref = 2.048;  break; 
        case 3: m_adcVref = 4.096;  break; 
    }
    if( m_adcVref > vdd ) m_adcVref = vdd; 

    uint8_t cdafvr = getRegBitsVal( newFVRCON, m_CDAFVR ); 
    switch( cdafvr ) {
        case 0: m_dacVref = 0.000;  break; 
        case 1: m_dacVref = 1.024;  break; 
        case 2: m_dacVref = 2.048;  break; 
        case 3: m_dacVref = 4.096;  break; 
    }
    if( m_dacVref > vdd ) m_dacVref = vdd; 

    if( !m_callBacks.isEmpty() )
    { for( McuModule* mod : m_callBacks ) mod->callBack();  }
}

double PicVrefE::getAdcVref()
{
    if( m_enabled ) return m_adcVref; 
    else            return 0; 
}

double PicVrefE::getDacVref()
{
    if( m_enabled ) return m_dacVref; 
    else            return 0; 
}
