/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#include <eCxx/eCxx.h>

#include "../AVR_Common.h"


//
// Check the MCU
//
#ifndef __AVR_ARCH_X__
#error "this test application is meant for AVRX platform only"
#endif


//
// For convenience
//
using AC = eCxx::AnalogComparator;


//
// The init function
//
void eCxx_user_init()
{
    // Initialize application
    initBasicAVRApp();

    // Initialize UART
    App::uart().begin(9600);

    // Set the ADC reference voltage to 4.34 V
    App::setADCReferenceVoltage(App::ADCVRef::Internal4V34);

    // Initialize analog comparator
    auto& ac = App::analogComparator();

    ac.inputp     = AC::InputP::P0;
    ac.inputn     = AC::InputN::Internal;
    ac.output     = AC::Output::Inverted;
    ac.acVRef     = AC::ACVRef::Internal2V50;
    ac.dacRef     = static_cast<eCxx::uint8_t>(2.0f / 2.5f * 255.0f); // Set the threshold at ~2.0 V
    ac.hysteresis = AC::Hysteresis::Large;

    ac.attachInterrupt(
        +[]() {
            // Read the current voltage using ADC
            const eCxx::uint32_t adcValTimes100 = (
                static_cast<eCxx::uint32_t>( App::analogRead(eCxx::AVR::AC0_InPos0) ) * 434 // 4.34 V reference voltage
            ) >> 10;
            // Send some information via UART
            App::uart().writeString   ( PGM_STR("AC0 interrupt : ")                          );
            App::uart().writeDecString( eCxx::Bool( App::analogComparator().getOutStatus() ) );
            App::uart().write         ( ' '                                                  );
            App::uart().write         ( '['                                                  );
            App::uart().writeDecString( adcValTimes100, 3                                    );
            App::uart().write         ( ']'                                                  );
            App::uart().write         ( '\n'                                                 );
        },
        App::InterruptMode::Change
    );

    ac.begin();
}


//
// The task function
//
void eCxx_user_task()
{
    // Process event
    App::processEvent();
}
