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


#ifndef ECXX_PLATFORM_ANALOG_JOYSTICK_H
#define ECXX_PLATFORM_ANALOG_JOYSTICK_H


#include <eCxx/CTL/MathUtility.h>
#include <eCxx/CTL/NumericLimits.h>


namespace eCxx {


//
// A simple reader class for two-axis analog joystick with one switch
//
// NOTE : The default template parameters assume 10-bit ADCs are used to read the analog values
//        of the joystick's axes.
//
template <typename ADCReaderT = Application, int8_t ToMin = -2, int8_t ToMax = 2, uint16_t FromMin = 0, uint16_t FromMax = 1023>
class AnalogJoystick : public Uncopyable {
    public:
        static constexpr int8_t   MapToMin   = ToMin;
        static constexpr int8_t   MapToMax   = ToMax;

        static constexpr uint16_t MapFromMin = FromMin;
        static constexpr uint16_t MapFromMax = FromMax;

    public:
        inline ~AnalogJoystick() = default;

    public:
        inline AnalogJoystick() noexcept;

        inline bool begin(uint8_t axis1Pin, uint8_t axis2Pin, uint8_t switchPin, bool reverseAxis1 = false, bool reverseAxis2 = false, ActiveState switchAS = ActiveState::Low) noexcept;
        inline void end() noexcept;

        inline void setMaxCoordinate(uint16_t maxA1, uint16_t maxA2);

        inline bool readRaw(int16_t& axis1Val, int16_t& axis2Val, bool& switchVal) noexcept;
        inline bool readCoordinates(uint16_t& axis1Val, uint16_t& axis2Val, bool& switchVal) noexcept;

    private:
        inline bool readRaw_impl() noexcept;

    private:
        uint8_t     _axis1Pin;
        uint8_t     _axis2Pin;
        uint8_t     _switchPin;
        bool        _revAxis1;
        bool        _revAxis2;
        ActiveState _switchAS;

        int16_t     _axis1Val;
        int16_t     _axis2Val;
        bool        _switchVal;

        uint16_t    _posA1Max;
        uint16_t    _posA2Max;

        uint16_t    _posA1;
        uint16_t    _posA2;
};


//
// Include the implementation file
//
#define INCLUDE_ECXX_PLATFORM_ANALOG_JOYSTICK_TPP
#include "AnalogJoystick.tpp"


} // namespace eCxx


#endif
