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


#include <eCxx/CTL/Types.h>

#include "PinName.h"


#ifndef ECXX_PLATFORM_AVRX_ANALOG_COMPARATOR_H
#define ECXX_PLATFORM_AVRX_ANALOG_COMPARATOR_H


#if defined(__AVR_ATmega808__) || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega4808__) || \
    defined(__AVR_ATmega809__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega3209__) || defined(__AVR_ATmega4809__)


namespace eCxx {


//
// A simple AVR analog comparator wrapper
//
class AnalogComparator : public Uncopyable {
    public:
        inline ~AnalogComparator() = default;

    private:
        AnalogComparator();

        friend class Application;

    public:
        // Positive input selection
        enum class InputP : uint8_t {
            // These values are derived from the datasheet
            P0 = 0x00, // Positive pin 0 (default)
            P1 = 0x01, // Positive pin 1
            P2 = 0x02, // Positive pin 2
            P3 = 0x03  // Positive pin 3
        };

        // Negative input selection
        enum class InputN : uint8_t {
            // These values are derived from the datasheet
            N0       = 0x00, // Negative pin 0 (default)
            N1       = 0x01, // Negative pin 1
            N2       = 0x02, // Negative pin 2
            Internal = 0x03  // Internal DAC voltage reference
        };

        // Output selection
        enum class Output : uint8_t {
            // These values are derived from the datasheet
            Disabled  = 0x00, // Disabled (default)
            Enabled   = 0x40, // Enabled
            Inverted  = 0xC0  // Inverted
        };

        // Voltage reference selection
        enum class ACVRef : uint8_t {
            // These values are derived from the datasheet
            Internal0V55 = 0x00, // Internal 0.55 V
            Internal1V10 = 0x01, // Internal 1.10 V
            Internal1V50 = 0x04, // Internal 1.50 V
            Internal2V50 = 0x02, // Internal 2.50 V
            Internal4V34 = 0x03, // Internal 4.34 V
            ExternalAVCC = 0x07  // External AVCC pin (default)
        };

        // Hysteresis selection
        enum class Hysteresis : uint8_t {
            Disabled = 0x00, // Disabled (default)
            Small    = 0x01, // ~10 mV
            Medium   = 0x02, // ~25 mV
            Large    = 0x03  // ~50 mV
        };

    public:
        // Configurable public properties
        InputP     inputp;
        InputN     inputn;
        Output     output;
        ACVRef     acVRef;
        uint8_t    dacRef; // Default = 0xFF
        Hysteresis hysteresis;

    public:
        bool begin();
        bool end();

        void reset();

        bool getOutStatus();

        void attachInterrupt(eCxx::VoidCallback userFunc, Application::InterruptMode mode);
        void detachInterrupt();
};


} // namespace eCxx


//
// Unsupported MCU
//
#else

#error "unsupported AVR MCU"

#endif


#endif
