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


#ifndef INCLUDE_ECXX_PLATFORM_SPECIFIC_PIN_DDX_H
#error "this file cannot be included directly"
#endif
#undef INCLUDE_ECXX_PLATFORM_SPECIFIC_PIN_DDX_H


#ifndef ECXX_PLATFORM_AVR_PIN_DDX_H
#define ECXX_PLATFORM_AVR_PIN_DDX_H


#define ECXX_DECLARE_ARRAY_FOR_DDX
#include "PinMapping.h"


namespace eCxx {


//
// A simple direct digital configure, read, and write wrapper class
//
template <uint8_t PinN>
class PinDDX : public Uncopyable {
    static_assert(PinN < sizeof(pin_to_pnum), "template argument substituting PinN is out of range");

    public:
        inline PinDDX() = default;
        inline ~PinDDX() = default;

    public:
        inline void pinModeOutput() const __ECXX_ATTR_ALWAYS_INLINE
        {
            *pnum_to_DDR[ pin_to_pnum[PinN] ] |= eCxx::pin_to_bitmask[PinN];
        }

        inline void digitalWrite(bool bit) const __ECXX_ATTR_ALWAYS_INLINE
        {
            if(bit) *pnum_to_PORT[ pin_to_pnum[PinN] ] |=  pin_to_bitmask[PinN];
            else    *pnum_to_PORT[ pin_to_pnum[PinN] ] &= ~pin_to_bitmask[PinN];
        }

    public:
        inline void pinModeInput() const __ECXX_ATTR_ALWAYS_INLINE
        {
            *pnum_to_DDR[ pin_to_pnum[PinN] ] &= ~eCxx::pin_to_bitmask[PinN];
        }

        inline void pinModeInput(bool withPullUp) const __ECXX_ATTR_ALWAYS_INLINE
        {
            pinModeInput();

            if(withPullUp) *pnum_to_PORT[ pin_to_pnum[PinN] ] |=  pin_to_bitmask[PinN];
            else           *pnum_to_PORT[ pin_to_pnum[PinN] ] &= ~pin_to_bitmask[PinN];
        }

        inline bool digitalRead() const __ECXX_ATTR_ALWAYS_INLINE
        {
            return *pnum_to_PIN[ pin_to_pnum[PinN] ] & pin_to_bitmask[PinN];
        }
};


} // namespace eCxx


#endif
